Using ANY in CASE statement - snowflake-cloud-data-platform

I have to implement logic where I need to use ANY in case statement. But I am not sure if this is allowed in Snowflake. The code looks like
SELECT CASE
WHEN (Field1 = ANY(array['a'::VARCHAR(24), 'b'::varchar(15), 'c'::varchar(20)])) THEN 'd'::varchar(16)
WHEN Condition 2 THEN abc
ELSE def
END AS xyz
Getting syntax error Unexpected ',' and unexpected ']'

Using IN:
In subquery form, IN is equivalent to = ANY and NOT IN is equivalent to <> ALL.
SELECT CASE WHEN Field1 IN ('a'::VARCHAR(24), 'b'::varchar(15), 'c'::varchar(20))
THEN 'd'::varchar(16)
WHEN Condition 2 THEN abc
ELSE def
END AS xyz
FROM tab;

assume you are referring to LIKE ANY but want it in the SELECT/CASE,
a CASE is actually almost the perfect form, as instead of saying any one of these, you can just "repeat" the WHEN clause of each of the valid instances.
Thus the original:
SELECT
CASE
WHEN (Field1 = ANY(array['a'::VARCHAR(24), 'b'::varchar(15), 'c'::varchar(20)])) THEN 'd'::varchar(16)
WHEN Condition 2 THEN abc
ELSE def
END AS xyz
can be written as:
SELECT
CASE
WHEN Field1 = 'a'::VARCHAR(24) THEN 'd'::varchar(16)
WHEN Field1 = 'b'::varchar(15) THEN 'd'::varchar(16)
WHEN Field1 = 'c'::varchar(20) THEN 'd'::varchar(16)
WHEN Condition 2 THEN abc
ELSE def
END AS xyz

Related

Achieve where condition and case statement if null

Below is my where condition in query
WHERE ResetID= CASE WHEN NOT EXISTS (select 1 FROM ops.table where LabelItemId=#Item) THEN NULL
WHEN #LastIssued < #LastDispatched THEN 1
WHEN #LastIssued >= #LastDispatched THEN 2
END
If case statement returns null the where condition will not work.. Any alternate solution for this condition without case
If you want to have NULL = NULL, you need to handle it with IS NULL. At a guess, what you want is this:
WHERE (ResetID = CASE WHEN NOT EXISTS (select 1 FROM ops.table where LabelItemId=#Item) THEN NULL
WHEN #LastIssued < #LastDispatched THEN 1
WHEN #LastIssued >= #LastDispatched THEN 2
END
OR (ResetID IS NULL AND NOT EXISTS (select 1 FROM ops.table where LabelItemId=#Item)))
Edit note that this does require 2 scans of the table ops.table; there may be a better way to do this, but difficult to suggest when we only have a snippet.

PostgreSQL JSON building an array without null values

The following query
SELECT jsonb_build_array(jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
END)
produces
[{"use":"Home"},null]
When I actually want
[{"use":"Home"}]
How do I go about doing this? json_strip_nulls() does not work for me.
By using a PostgreSQL array like that:
SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END], null))
which does produce:
[{"use": "Home"}]
while, to be sure:
SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END,
jsonb_build_object('real_use', 'NotHome')], null))
does produce:
[{"use": "Home"},{"real_use": "NotHome"}]
Creating a custom function seems to be the simplest way.
create or replace function jsonb_build_array_without_nulls(variadic anyarray)
returns jsonb language sql immutable as $$
select jsonb_agg(elem)
from unnest($1) as elem
where elem is not null
$$;
select
jsonb_build_array_without_nulls(
jsonb_build_object('use', 'home'),
case when 1 = 2 then jsonb_build_object('use', 'work') end
)
jsonb_build_array_without_nulls
---------------------------------
[{"use": "home"}]
(1 row)
I'm assuming this query is generaetd dynamically, somehow. If you're in control of the SQL generation, you can also use ARRAY_AGG(...) FILTER(...) instead, which, depending on your real world query, might be more convenient than using all the different array conversion functions suggested by Patrick.
SELECT (
SELECT json_agg(v) FILTER (WHERE v IS NOT NULL)
FROM (
VALUES
(jsonb_build_object('use', 'Home')),
(CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
) t (v)
)
Or also:
SELECT (
SELECT json_agg(v)
FROM (
VALUES
(jsonb_build_object('use', 'Home')),
(CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
) t (v)
WHERE v IS NOT NULL
)
One other way that this can be handled is the following:
SELECT jsonb_build_array(
jsonb_build_object('use', 'Home'),
CASE
WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
ELSE '"null"'
END
) - 'null'
(Unfortunately it's not really possible to do much with null by itself in postgres -- or most other DBs)
In the case above, '"null"' could be replaced with just about any unique string that would not be mistaken for live data in the array. I would not use numbers since - 0 would actually try to remove the first item from the array, rather than a number within the array. But you could probably use '"0"' and remove using something like - '0' if you wanted.
For those not using CASE, a COALESCE could be used to convert nulls into the desired string (alas, no NVL, IFNULL or ISNULL in postgres, but at least COALESCE is portable)

SQL CASE when text field is NULL not working

I'm trying to run the following case statement in SQL:
CASE
WHEN P.Photos_Cloned_From IS NULL
THEN 'http://www.toolboxbarn.com/v/vspfiles/photos/'+P.ProductCode+'-2T.jpg'
ELSE 'http://www.toolboxbarn.com/v/vspfiles/photos/'+P.Photos_Cloned_From+'-2T.jpg'
END AS image_link,
The statements works, but only for those records that are not NULL. For items that are NULL, the statement is not returning the THEN condition.
Any suggestions?
Try this and let us know what happens.
'http://www.toolboxbarn.com/v/vspfiles/photos/'+
COALESCE(P.Photos_Cloned_From,P.ProductCode,'DEFAULT')+'-2T.jpg'
AS image_link,
Using coalesce here is better than the case statement. Some platforms can optimize coalesce and it lets you easily make a default value.
#hogan's Suggestion is a great one to save code, but ultimately it should have the same result as your case statement if you don't introduce his new 'default' case. It is most likely that the ProductCode is also NULL is that a possibility?
Why string + NULL = NULL because NULL is an unknown in sql most db platforms will nullify the entire value when null is aggregated or concatenated.
So Think of the following test cases:
Id ProductCode Photos_Cloned_From
1 1 ClonedFrom
2 2 Null
3 NULL Null
The results of your case expression and Hogan's Suggestion would be:
1) ELSE 'http://www.toolboxbarn.com/v/vspfiles/photos/ClonedFrom-2T.jpg'
2) WHEN 'http://www.toolboxbarn.com/v/vspfiles/photos/2-2T.jpg'
3) WHEN NULL
CASE WHEN ISNULL(P.Photos_Cloned_From,'') = '' THEN 'http://www.toolboxbarn.com/v/vspfiles/photos/'+P.ProductCode+'-2T.jpg'
ELSE 'http://www.toolboxbarn.com/v/vspfiles/photos/'+P.Photos_Cloned_From+'-2T.jpg'
END AS image_link,
SELECT
F.Name
, F.Address
, F.InDate
, ( CASE WHEN (F.Date_Down IS NULL and F.Cod_Down = 0 )THEN 0 ELSE -1 END) as 'sn_Down'
FROM
Folders F

case when but two columns instead of one column

I need some advice and suggestions if there is available some way of doing something like this:
SELECT Status=Case
WHEN clflf.product='active'
THEN 'Active' ELSE 'NotActive' END;
this basically creates active or notactive in one column.
Is there some way of doing a case when or some other technique so that I can have two columns, 'Active' and 'NotActive'?
You need separate case statements, like so.
Select StatusActive = Case when clflf.product='active' then 1 ELSE 0 end
,StatusNotActive = Case when clflf.product <>'active' then 1 ELSE 0 end
You can always do
SELECT active,
1 - active AS notactive
FROM clflf
CROSS APPLY (SELECT CASE
WHEN clflf.product = 'active' THEN 1
ELSE 0
END) CA(active)

Using a bit input in stored procedure to determine how to filter results in the where clause

I'm beating my head against the wall here... can't figure out a way to pull this off.
Here's my setup:
My table has a column for the date something was completed. If it was never completed, the field is null. Simple enough.
On the front end, I have a checkbox that defaults to "Only show incomplete entries". When only pulling incomplete entries, it's easy.
SELECT
*
FROM Sometable
WHERE Completed_Date IS NULL
But offering the checkbox option complicates things a great deal. My checkbox inputs a bit value: 1=only show incomplete, 0=show all.
The problem is, I can't use a CASE statement within the where clause, because an actual value uses "=" to compare, and checking null uses "IS". For example:
SELECT
*
FROM Sometable
WHERE Completed_Date IS <---- invalid syntax
CASE WHEN
...
END
SELECT
*
FROM Sometable
WHERE Completed_Date =
CASE WHEN #OnlyIncomplete = 1 THEN
NULL <----- this translates to "WHERE Completed_Date = NULL", which won't work.. I have to use "IS NULL"
...
END
Any idea how to accomplish this seemly easy task? I'm stumped... thanks.
...
WHERE #OnlyIncomplete = 0
OR (#OnlyIncomplete = 1 AND Completed_Date IS NULL)
Hmmm... I think what you want is this:
SELECT
*
FROM Sometable
WHERE Completed_Date IS NULL OR (#OnlyIncomplete = 0)
So that'll show Date=NULL plus, if OnlyIncomplete=0, Date != Null. Yeah, I think that's it.
If you still want to use a CASE function (although it may be overkill in this case) :
SELECT
*
FROM Sometable
WHERE 1 =
(CASE WHEN #OnlyIncomplete = 0 THEN 1
WHEN #OnlyIncomplete = 1 AND Completed_Date IS NULL THEN 1
END)

Resources