Add diferent condition into where clause depending on case condition - sql

If column A is not empty I should add one condition and if it is empty, then I should add another condition. Something like this:
select *
from table t
where case when len(t.A) > 0 then t.A = (select B from anothertable )
else t.C = (select D from anothertable)
As this does not compiles, and I can't use IF clause within WHERE is there any other way to achieve this?

We can rephrase the login in the WHERE clause to make it work:
SELECT *
FROM table_t
WHERE
(LEN(t.A) > 0 AND t.A IN (SELECT B FROM anothertable) ) OR
(LEN(t.A) <= 0) AND t.C IN (SELECT D FROM anothertable) );
To address the comment by #HoneyBadger if the subqueries on anothertable return more than one record, then this query would error out if we used t.A = (subquery). If you intend to use equals, then you would have to ensure that the subquery only returns a single record. Your suggestion to use WHERE IN might fix the problem.

Related

Evaluate no result condition in SQL CASE

I would like to use the SQL CASE keyword to evaluate the result of an inner query, in particular to check whether there is no record:
PseudoCode:
UPDATE tableA AS outerTable
SET field = CASE
WHEN (
SELECT *
FROM tableB
WHERE innerField = outerTable.field
) IS [doesn't have result]
THEN (
...
)
ELSE "default"
END
How can I code this condition? I've tried with IS NULL but it doesn't seem to work (
Scalar subquery produced more than one element)
You are looking for NOT EXISTS:
WHEN NOT EXISTS (SELECT *
FROM tableB b
WHERE b.innerField = outerTable.field
)
THEN . . .

Snowflake, SQL where clause

I need to write query with where clause:
where
pl.ods_site_id in (select id from table1 where ...)
But if subquery (table1) didn't return anything, where clause doesn't need to include in result query (like it returns TRUE).
How can I do it? (I have snowflake SQL dialect)
You could include a second condition:
where pl.ods_site_id in (select id from table1 where ...) or
not exists (select id from table1 where ...)
This explicitly checks for the subquery returning no rows.
If you are willing to use a join instead, Snowflake supports qualify clause which might come in handy here. You can run this on Snowflake to see how it works.
with
pl (ods_site_id) as (select 1 union all select 5),
table1 (id) as (select 5) --change this to 7 to test if it returns ALL on no match
select a.*
from pl a
left join table1 b on a.ods_site_id = b.id -- and other conditions you want to add
qualify b.id = a.ods_site_id --either match the join condition
or count(b.id) over () = 0; --or make sure there is 0 match from table1

using define to store the result of a select statement

Good evening, i want to ask about the feasibility of something so i have a select statement inside this select a lot of similare subqueries
i want to use a sub-query only once and store it's result I have tried something like that but I don't know what to do
any help would be appreciated
define A = Select somthing from TableA
Select case
when A <0
then 1
else 2
End as selectedcolumn from TableB
But i think that define is used only with static values
You can do this with a CTE, e.g.
WITH A AS
SELECT COUNT(*) c FROM TableA A
WHERE A.ColumnA = B.ColumnB
AND A.ColumnA2 = 0
Select A.c As test
from TableA ta
inner join TableB tb
on ta.columnA=tb.columnB
cross join A
This will make A.c available in your query. You can also then do (select c from A) anywhere in your query to get the value.
Alternately, if you're running a script in SQL*Plus, you can define a column variable using new_value:
COLUMN my_count NEW_VALUE my_constant
SELECT COUNT(*) my_count FROM TableA A
WHERE A.ColumnA = B.ColumnB
AND A.ColumnA2 = 0;
Then you can refer to it later on in your script using the substitution string &&my_constant:
Select case
when &&my_constant <0
then 1
else 2
End as selectedcolumn from TableB

SQL left join to remove duplicates

I have the following data table:
Table:
ID Event
A 1
A ?
B ?
I want to write a SQL query so that I can remove duplicate ID's with preference for actual values over '?'. I can also guarantee that the only duplicates are for IDs that have a regular event (value 1-9) as well as a '?' event. So in the case above, my query should return:
ID Event
A 1
B ?
I want my query to return the rows that match this description as well as all the columns for those rows. My attempt so far is a left join:
sel L.*
from table L
left join table R
on L.ID = R.ID and
(L.Event is null and R.Event is not null)
where R.ID is null
This seems to partially work. It's able to remove duplicates but somehow for the case where there is a non duplicate ID like B with a '?" event in the above example, that row is removed. However, there are other cases where the same case is kept.
Why is this happening? I would think that might join on condition is correct since I check for when
R.Event is not null
but something is evidently wrong in my logic. Any help would be greatly appreciated.
There are multiple ways to solve this problem, but left join just doesn't come to mind.
How about this?
select t.*
from t
where event <> '?'
union all
select t.*
from t
where event = '?' and
not exists (select 1 from t t2 where t2.id = t.id and t2.event <> '?');
For these values, you could also use group by:
select id, min(event)
from t
group by id;
But aggregation would not keep all the other values in the row.
Or, a general approach to such prioritization queries is row_number():
select t.*
from (select t.*,
row_number() over (partition by id
order by (case when event = '?' then 1 else 2 end) desc
) as seqnum
from t
) t
where seqnum = 1;

SQL Conditional filter with different values

I have found lots of posts on coniditonal filtering in the where clause, but they all seem to be based off of using the same value, such as:
WHERE (o.OrderID = #orderid OR #orderid IS NULL)
I need to do something slightly different, I need to remove a filter and its value completely base on another value, so something like:
select *
from tableA
where 1 = 1
case when a = 1 then
and b in (select b from tableB)
else
-- do nothing
end
I know that the above is not allowed, and I am just writing as an example of what I am trying to do. does Anyone have any idea of a good way to do this? I know i could use if statements and duplicate the query, but it is a large one, and i am trying to avoid that.
Thanks
SELECT *
FROM tableA
WHERE a <> 1
OR (a = 1 AND EXISTS(SELECT b from TableB WHERE tableA.b = TableB.b))
You could also write this as:
SELECT tableA.*
FROM tableA
LEFT JOIN tableB
ON tableA.b = tableB.b
WHERE tableA.a <> 1
OR (tableA.a = 1 AND tableB.b IS NOT NULL)
"Correcting" your WHERE clause:
select *
from tableA
where 'T' = case
when a = 1 then case
when b in (select b from tableB) then 'T'
end
else 'T'
end;