SQL Server GROUP BY NULL - sql

I am using SQL Server and I have to group by a few columns but only if a setting is true.
DECLARE #setting tinyint
SET #setting = 0
SELECT col1 FROM table1
GROUP BY col1,
CASE WHEN #setting = 1 THEN col2 ELSE NULL END
OR should I default to col1 that I always use to group by if the setting is set, so the code would would be
CASE WHEN #test = 1 THEN col2 ELSE col1 END
It does actually work to use the NULL but I can't find an example on the internet to prove that it is correct usage.

SELECT col1 FROM table1
GROUP BY col1,
CASE WHEN #setting = 1 THEN col2 ELSE NULL END
Your usage is correct. You already know it works.
ELSE NULL is implied in CASE, so you could have written it as
GROUP BY col1, CASE WHEN #setting = 1 THEN col2 END
You could try to be coy with variants like
GROUP BY col1, #setting * col2 --for numeric col2
GROUP BY col1, COALESCE(NULLIF(#setting,1), col2)
But the CASE statement actually unrolls to a better, simpler plan.

DECLARE #setting tinyint
SET #setting = 0
SELECT col1 FROM table1
GROUP BY col1,
CASE WHEN #setting = 1 THEN col2 ELSE NULL END
your first example should work.
For further clarification, do you want to group by col1, col2 or group by col1 when #setting = 1?
edit: Your first example is correct.

Related

Comparing two columns in the same table

I have two columns and I want to compare the values in each row and create a third column that will tell me true or false (or 0/1) like the below example.
Col1 Col2 Col3
24 24 true
45 45 true
56 54 false
78 98 false
Personally a CASE expression is probably the easiest and simplest way to do this.
SELECT col1,
col2,
CASE
WHEN col1 = col2 THEN 'True'
ELSE 'False'
END AS Is_A_Match
This should work for you:
select col1, col2, case when col1 = col2 then 'true' else 'false' end as col3
If you want to add a column into the table, then you can use a computed column:
alter table t add col3 as (case when col2 = col3 then 1 else 0 end)
If the columns can have NULL values and you want to treat those as equal, then the logic should take this into account.
This column is then available when referring to the table.
If you just want the result in a query, use a case expression as described in several other answers.
Simply use a case expression.
case when col1 = col2 then 'true' else 'false'
or in bit form
case when col1 = col2 then 1 else 0

Nested Case for hard coding result of a case statement

I have a dataset similar to this;
col1 col2 col3
1 YES NO
2 NO YES
I am trying to apply case statement,
case when col1 = 1 then col2
when col1 = 2 then col3 end as newcol
Now the newcol will have values as YES/NO in the output. Is it possible to apply another case inside the above case condition, So that I can hardcode YES as Y and NO as N.
I have got the result by adding a case statement in the an outer query. Is there any alternate approach like nested case.
Also can I apply case condition using the column alias newcol?
You can add a case expression around your case, like this:
case (
case
when col1 = 1 then col2
when col1 = 2 then col3
end
) when 'YES' then 'Y' else 'N' end as newcol
SUBSTR would pick the first character of YES or NO without a conditional:
SUBSTR(
case
when col1 = 1 then col2
when col1 = 2 then col3
end
, 1
, 1
) as newcol

Get record with a field egal to a specific value else with null

I want in SQL : if a field is equal to a specific value, I want this record if not I want the record with this field equal to null.
I can try to that:
SELECT TOP 1 COL1, COL2, COL3
FROM TABLE1 WHERE (COL2 = MY_SPECIFIC_VALUE OR COL2 IS NULL) AND COL3 = '42'
AND COL1 = 3
But, what is the result returned? The smallest id? Or it is not specified?
Assuming that this is the real question:
If a field is equal to a specific value, I want this record if not I want the record with this field equal to null.
You can do this as:
SELECT TOP 1 COL1, COL2, COL3
FROM TABLE1
WHERE (COL2 = MY_SPECIFIC_VALUE or COL2 IS NULL) AND
COL3 = '42' AND COL1 = 3
ORDER BY (CASE WHEN COL2 = MY_SPECIFIC_VALUE THEN 1 ELSE 2 END);

SQL Server Select a row for where a column value does not exists

I have a table as
COl1____COL2____COL3
1_________1_____val1
1_________2_____val2
1_________3_____val3
2_________1_____val1
2_________2_____val2
2_________3_____val3
3_________1_____val1
3_________2_____val2
3_________4_____val4
No I want to have unique values from COL1 such that it should only show me COL1 value that does not have a value "3" under COL2
i.e. I want a query to return me
Result
3
Any help is much appreciated
SELECT col1
FROM YourTable
EXCEPT
SELECT col1
FROM YourTable
WHERE col2 = 3
Or
SELECT col1
FROM YourTable
GROUP BY col1
HAVING MAX(CASE
WHEN Col2 = 3 THEN 1
ELSE 0
END) = 0
select col1
from Tab
where col1 not in (select col1 from tab where col2 = 3)

Using "like" inside a "case" statement with 2 different fields

I have 2 fields in my table on which i need a case statement.
Col1 Col2 Col3
abc.txt Y 0
def.txt N 0
bbck.txt Y 1
The Col3 values are based on the Col1 and Col2 values in the following manner.
Y = 1 and N = 0. So all the values in Col2 that are Y shall become 1 in col3, and Nin Col2 will become 0 in Col3, UNLESS the col1 value ends with %c.txt. As you can see since the abc.txt ends with %c.txt the value in col3 becomes 0.
I know this can be done with a CASE statement nested maybe to get this done. Does anyone know how to?
here's my code
SELECT
CASE Col2
WHEN 'Y' THEN '1'
WHEN 'N' THEN '0'
ELSE
(CASE WHEN [Col1] LIKE '%c.txt' THEN '0'
END)
END
AS Col3,
*
FROM Tabl1
Hope this gives an idea
Maybe:
SELECT
CASE
WHEN Col2 = 'N'
OR Col1 LIKE '%c.txt'
THEN '0'
WHEN Col2 = 'Y'
THEN '1'
END AS Col3
, *
FROM Tabl1
SELECT
CASE WHEN Col2 LIKE '%c.txt' THEN '0'
ELSE
CASE
WHEN Col2 = 'N' THEN '0'
WHEN Col2 = 'Y' THEN '1'
END
END AS COL3
FROM Tabl1
I don't think your spec is clear enough e.g. is the comma before the word "UNLESS" suposed to incidicate that the following clause applies to both the previous clauses?
There seems to be four possible combinations:
1) Col1 LIKE '%c.txt'
AND Col2 = 'Y'
2) Col1 LIKE '%c.txt'
AND Col2 = 'N'
3) Col1 NOT LIKE '%c.txt'
AND Col2 = 'Y'
4) Col1 NOT LIKE '%c.txt'
AND Col2 = 'N'
You say
i need a case statement
Is this true? With SQL, the same thing can always be achieved multiple ways (which is why it is so hard to build a good optimizer :) I think a spec should state what is required and not place unreasonable restrictions on how to implement it.
The following uses UNION rather than case and if you had considered this from the start then maybe your spec would be better ;)
WITH Tabl1
AS
(
SELECT *
FROM (
VALUES ('abc.txt', 'Y'),
('def.txt', 'N'),
('bbck.txt', 'Y'),
('disc.txt', 'N')
) AS T (Col1, Col2)
)
SELECT '0' AS Col3, *
FROM Tabl1
WHERE Col1 LIKE '%c.txt'
AND Col2 = 'Y'
UNION
SELECT '0' AS Col3, *
FROM Tabl1
WHERE Col1 LIKE '%c.txt'
AND Col2 = 'N'
UNION
SELECT '1' AS Col3, *
FROM Tabl1
WHERE Col1 NOT LIKE '%c.txt'
AND Col2 = 'Y'
UNION
SELECT '0' AS Col3, *
FROM Tabl1
WHERE Col1 NOT LIKE '%c.txt'
AND Col2 = 'N';
P.S. I coded this to match the accepted answer but I'm not convinced it is correct!
This might be what your looking for:
SELECT * FROM Tabl1
cross apply
(
select Col3 =
CASE
WHEN Tabl1.Col2 = 'Y' then '1'
WHEN Tabl1.Col2 = 'Y' then '1'
WHEN RIGHT(Tabl1.Col1, 6) = 'c.txt' then '0'
END
) as Col3