SQL Server Where Clause Case Statement? - sql

I have a Where Clause that checks the existence of rows in a subquery, but I only want to execute that check if a bit is set to 1. So for example:
Select * from Listing l
Where
l.IsDeleted=1
AND CASE WHEN #MustHasPicture = 1 THEN
(
EXISTS
(
SELECT NULL AS [EMPTY]
FROM [dbo].[ListingPictures] AS [lp]
INNER JOIN Listing l ON lp.ListingID=l.ID
)
)
ELSE 1 END = 1
This syntax is wrong, and I'm hoping someone can point me in the right direction. Thanks.

SELECT *
FROM Listing l
WHERE IsDeleted = 1
AND ( #MustHasPicture <> 1 OR
(#MustHasPicture = 1 AND l.id IN (
SELECT listingid
FROM ListingPictures
)
)
)

No need to do a case - if the first part of an and fails, the second part will not be performed.
select
*
from
Listing l
Where
l.IsDeleted = 1
and ((#MustHasPicture = 1 and exists (...)) or 1)

What about this one:
SELECT * FROM Listing l
WHERE l.IsDeleted = 1
AND (#MustHasPicture = 1
AND EXISTS(SELECT * FROM [dbo].[ListingPictures] AS [lp]
WHERE lp.ListingID = l.ID)
OR #MustHasPicture = 0)
But where does the Value #MustHasPicture come from?

Related

SQL query having CASE WHEN EXISTS statement

I trying to create a SQL query with a CASE WHEN EXISTS clause in SQL Server. I assume I am doing something wrong as when I run the SELECT * FROM [Christmas_Sale] it takes forever for SQL to load the code.
CREATE VIEW [Christmas_Sale]
AS
SELECT
C.*,
CASE
WHEN EXISTS (SELECT S.Sale_Date
FROM [Christmas_Sale] s
WHERE C.ID = S.ID)
THEN 0
ELSE 1
END AS ChristmasSale
FROM
[Customer_Detail] C ;
I'm trying to write a sub select which I need to return a 1 if Sale_Date= 1 and 0 for anything else.
The syntax of your query looks ok. But since your stated:
I'm trying to write a sub select which I need to return a 1 if Sale_Date= 1 and 0 for anything else.
... Then you could rephrase your query by adding one more condition in the WHERE clause of the subquery:
CREATE VIEW [Christmas_Sale]AS
SELECT
C.*,
CASE WHEN EXISTS (
SELECT 1
FROM [Christmas_Sale] s
WHERE C.ID = S.ID and S.Sale_Date = 1
) THEN 0 ELSE 1 END AS ChristmasSale
FROM [Customer_Detail] C ;
If a record exists in [Christmas_Sale] with the corresponding ID and Sale_Date = 1, then ChristmasSale will have value 1, else it will display 0.
This query looks correct:
CREATE VIEW [Christmas_Sale] AS
SELECT C.*,
(CASE WHEN EXISTS (SELECT 1
FROM [Christmas_Sale] s
WHERE C.ID = S.ID
)
THEN 0 ELSE 1
END) AS ChristmasSale
FROM [Customer_Detail] C ;
If performance is an issue, you want an index on Christmas_Sale(ID).
Note that the SELECT S.Sale_Date in the subquery is meaningless, because EXISTS checks for rows not columns. Hence, I replaced it with the simpler 1.

Select values where tow different conditions

I have a Questions group table like follows:
ID, NAME, DESCRIPTION, VERSION_ID
Versions table columns are:
ID, NUMBER, VERSION_STATE
VERSION_STATE is an enumerated that can be 0, 1 or 2.
I need to select all questions group that its version has thevVERSION_STATE 0 or 1, but if there is a questions group with a VERSION_STATE = 0 I don't have to return the questions group with the VERSION_STATE = 1.
The simplest approach is:
SELECT distinct QG.id FROM healthsafety.hs_questions_group QG
LEFT OUTER JOIN (SELECT * FROM healthsafety.hs_version) VERSION
ON QG.VERSION_ID = VERSION.ID
WHERE
VERSION.VERSION_STATE=0
OR VERSION.VERSION_STATE=1
The problem is that this query returns all questions group with the VERSION_STATE 0 or 1. If I remove the or clause, and there are not questions groups with VERSION_STATE = 0, I need to return the questions groups with VERSION_STATE = 1.
I think that I need an if else or case statement but I am stucked. Any Idea?
Note that I have to implement this using criteria, so I need to use the simplest solution.
SELECT *
FROM (
SELECT OG.ID,OG.NAME,OG.DESCRIPTION,VERSION.ID,VERSION.NUMBER,VERSION.VERSION_STATE,ROW_NUMBER()OVER(PARTITION BY OG.ID ORDER BY VERSION.VERSION_STATE ASC) as INDICATOR
FROM healthsafety.hs_questions_group QG
LEFT OUTER JOIN
(SELECT * FROM healthsafety.hs_version) VERSION
ON QG.VERSION_ID = VERSION.ID
WHERE
VERSION.VERSION_STATE=0
OR VERSION.VERSION_STATE=1
) AS ABC
WHERE (ABC.VERSION_STATE = 0 and ABC.INDICATOR = 1)
OR (ABC.VERSION_STATE = 1 and ABC.INDICATOR = 1)
Using a common table expression and a union all where the second query uses not exists() to only return rows where version_state=1 when rows with version_state=0 do not exist.
;with cte as (
select qg.id, v.version_state
from healthsafety.hs_questions_group qg
inner join healthsafety.hs_version version v
on qg.version_id = v.id
where v.version_state in (0,1)
)
select id
from cte
where version_state = 0
union all
select qg.id
from cte
where version_state = 1
and not exists (
select 1
from cte
where version_state = 0
)

sql function case returns more than one row

Going to use this query as a subquery, the problem is it returns many rows of duplicates. Tried to use COUNT() instead of exists, but it still returns a multiple answer.
Every table can only contain one record of superRef.
The below query I`ll use in SELECT col_a, [the CASE] From MyTable
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = myTable.sysno AND A_specAttr = 'value')
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo WHERE C_superRef = myTable.sysno AND b_type = 2)
THEN 2
ELSE (SELECT C_intType FROM C
WHERE C_superRef = myTable.sysno)
END
FROM A, B, C
result:
3
3
3
3
3
3...
What if you did this? Because Im guessing you are getting an implicit full outer join A X B X C then running the case statement for each row in that result set.
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM ( SELECT COUNT(*) FROM A ) --This is a hack but should work in ANSI sql.
--Your milage my vary with different RDBMS flavors.
DUAL is what I needed, thanks to Thorsten Kettner
SELECT CASE
WHEN
EXISTS (SELECT 1 FROM A WHERE
A_superRef = 1000001838012)
THEN 3
WHEN EXISTS (SELECT 1 FROM B
INNER JOIN С ON С_ReferenceForB = B_sysNo AND C_superRef = 1000001838012 )
THEN 2
ELSE (SELECT C_type FROM C
WHERE C_superRef = 1000001838012)
END
FROM DUAL

Compare Count From Outer SELECT in a Nested SELECT?

I have this SQL Query,
select * from (select * from .......) as a
where 1 = case when CountOfInnerSelect = 1 Then 1 ELSE ............
Is it possible I can get Count of inner select inside the outer SELECT?
Your WHERE Clause does not make much sense as it is applied like a filter here. (ie; similar to WHERE myCount = 1)
SELECT * FROM
(SELECT c1,c2,c3,..,Cn,COUNT(*) AS myCount
FROM YourTable
GROUP BY c1,c2,c3,..,Cn
) A
WHERE 1 = CASE myCount WHEN 1 THEN 1 ELSE... END
Yes :
select * from (select count(0) as cnt from .......) as a
where 1 = case when a.cnt = 1 Then 1 ELSE ............

Errors usually but within EXISTS sub-query it runs

Is the following problematic?
DELETE a
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData a
WHERE EXISTS
(
SELECT *
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData b
WHERE
b.[Past28Days] = 1 AND
a.[Index] = b.[Index]
HAVING SUM(b.Amount) = 0
)
Reason I'm slightly uneasy about using the above script is that if I run the following it errors:
SELECT *
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData b
WHERE
b.[Past28Days] = 1
HAVING SUM(b.Amount) = 0
I understand why this script errors => the select is not grouped on anything therefore the processor does not like the aggregation in the HAVING clause.
But as a sub-query this error does not occur - why? Is this a problematic approach?
EDIT
Ended up using the following:
DELETE a
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData a
WHERE a.[Index] IN
(
SELECT [Index]
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData
WHERE [Past28Days] = 1
GROUP BY [Index]
HAVING SUM(Amount) = 0
)
But as suggested in answer the following is more readable by simply adding the GROUP BY into the sub-query:
DELETE a
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData a
WHERE EXISTS
(
SELECT *
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData b
WHERE
b.[Past28Days] = 1 AND
a.[Index] = b.[Index]
GROUP BY b.[Index]
HAVING SUM(b.Amount) = 0
)
It is legal to omit group by and still perform aggregations, therefore having is still a way of limiting results:
select sum(x)
from
(
select 1 x union all select 2
) a
having sum(x) = 3
Exists() work because everything in select list is ignored. Exists() looks for rows only, and terminates as soon as one is found. You might add group by b.Index to make intent clear to anyone reviewing the code later, or rewrite it using inner join and derived table.
DELETE a
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData a
INNER JOIN
(
SELECT b.[Index]
FROM WHAnalysis.dbo.tb_r12027dxi_CalculatedData b
WHERE
b.[Past28Days] = 1
GROUP BY b.[Index]
HAVING SUM(b.Amount) = 0
) b1
ON a.[Index] = b1.[Index]