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

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

Related

Use Case and if to check values

I am trying to do some calculated column, my scenario is like the below example.
e.g: Whenever col1 is 'Yes', check Col2, if it has any value then calculated column will be 'True'.
Whenever Col1 is 'No', then calculated column will be 'Unknown'.
Whenever col1 is 'Yes', check Col2, if it is null then calculated column will be 'False'.
Col1 Col2 CalculatedColumn
Yes 123 True
No null Unknown
yes null False
Any help how can I achieve that?
You would use case:
select (case when col1 = 'Yes' and col2 is not null then 'True'
when col1 = 'No' then 'Unknown'
when col1 = 'Yes' and col2 is null then 'False'
end) as calculated_column
This can be simplified to:
select (case when col1 = 'Yes' and col2 is not null then 'True'
when col1 = 'Yes' then 'False'
else 'Unknown'
end) as calculated_column
You can use CASE..WHEN clause to meet this requirement. Converting your requirements in CASE..WHEN clause -
case when col1 = 'Yes' and col2 is not null then 'True'
when col1 = 'Yes' and col2 is null then 'False'
when Col1 = 'No' or col1 is null then 'Unknown' end as calculated_col

Issue with Insert Into due to data types

I'm trying to run this:
INSERT INTO (Col1, Col2, Col3, etc. )
SELECT Col1, Col2, Col3, etc.
FROM MYTABLE
The problem is, that I have some NAs and NULLS in several fields. I overcame the issue with the INT data type.
CONVERT(INT, CASE WHEN IsNumeric([Col1]) = 1 THEN [Col1] ELSE 0 END)
I thought the line below would work for decimals, but it doesn't.
CONVERT(DECIMAL, CASE WHEN IsNumeric([Col2]) = 1 THEN [Col2] ELSE 0 END)
Is there some way around this? Again, I think it's the NAs and NULLS that's throwing things off. I am using SQL Server 2018. Thanks.
Use TRY_CONVERT()!
TRY_CONVERT(DECIMAL, [Col2])
If you want 0 when this fails, add COALESCE():
COALESCE(TRY_CONVERT(DECIMAL, [Col2]), 0)
Please check below select query which will give you only numeric values from columns which has NULL and NA values.
SELECT
CASE WHEN ISNUMERIC(COL1) = 1 THEN COL1 ELSE 0 END COL1,
CASE WHEN ISNUMERIC(COL2) = 1 THEN CONVERT(NUMERIC(10,2),COL2) ELSE 0.00 END COL2,
CASE WHEN ISNUMERIC(COL3) = 1 THEN CONVERT(NUMERIC(10,2),COL3) ELSE 0.00 END COL3
FROM
(
SELECT '1' AS COL1, '2.05' AS COL2,'52.52' AS COL3 UNION ALL
SELECT NULL AS COL1, '6' AS COL2, 'NA' AS COL3 UNION ALL
SELECT 'NA' AS COL1, NULL AS COL2, NULL AS COL3 UNION ALL
SELECT '2' AS COL1, 'NA' AS COL2,'25.63' AS COL3
) X
Note: When decimal column has bigger value like "123456789.52" than you will get "Arithmetic overflow" error.

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 GROUP BY NULL

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.