using a CASE within WHERE - sql-server-2008

I have code where I need to add filter into where clause that varies based on value of variable. As in example below if #X has a value of 0 then I want
to include a filter for OrderID = 10; otherwise I want to add filter for OrderID = 20 with another filter for DepartmentID either been NULL or a value of 30. This could be accomplished using a IF ELSE as below
DECLARE #X INT
-- Retrieve value for #X
IF #X = 0
BEGIN
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND OrderID = 10
END
ELSE
BEGIN
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND OrderID = 20 AND ( DepartmentID IS NULL OR DepartmentID = 30)
END
I wonder if there is someway of doing it using one SQL statement. I thought it's doable using CASE within a WHERE but SQL does not seem to allow below.
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND CASE WHEN #X = 0 THEN OrderID = 10 ELSE OrderID = 20 AND ( DepartmentID IS NULL OR DepartmentID = 30) END
Is there anyway of accomplishing this.

you were close,
AND OrderID = (CASE WHEN #X = 0 THEN 10 ELSE 20 END)
AND DepartmentID = (CASE WHEN #X = 0 THEN DepartmentID ELSE 30 END)

SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND OrderID = CASE WHEN #X = 0 THEN 10 ELSE 20 END
AND ISNULL(DepartmentID,30) = CASE WHEN #X = 0 THEN ISNULL(DepartmentID,30) ELSE 30 END

You can do that without a CASE:
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND ((#X = 0 AND OrderID = 10) OR (#X <> 0 AND OrderID = 20 AND DepartmentID = 30))
Edit:
With the condition that you wanted to add:
SELECT *
FROM Customers
WHERE ProductID IS NOT NULL
AND ((#X = 0 AND OrderID = 10) OR (#X <> 0 AND OrderID = 20 AND (DepartmentID IS NULL OR DepartmentID = 30)))

Related

MySql select statement with conditional where clause

I am trying to write a MySql statement with a conditional where clause.
something like this:
set #price = 5000 ;
set #city = 1324368075;
select count(*)
from property
where case when #price is not null then
price < #price
end
and (case when #city is not null then
CityId = #city
end)
the variable should be included in the query only if it is not null.
My attempts have failed so far. Any ideas?
Edited:
Sorry I spoke too soon ysth,
these two queries are supposed to yield the same count but they dont.
Edit #2: Execution plan & indexes
Here's the query:
set #CountryId = null ;
set #CityId = 1324368075 ;
set #StateProvince = null ;
set #CategoryId = null ;
set #TransactionTypeId = null;
set #Price = 5000;
SELECT
Count(*)
FROM
meerkat.property
WHERE
(CASE WHEN #CountryId IS NOT NULL THEN CountryId = #CountryId ELSE 1 END)
AND (CASE WHEN #CityId IS NOT NULL THEN CityId = #CityId ELSE 1 END)
AND (CASE WHEN #CategoryId IS NOT NULL THEN CategoryId = #CategoryId ELSE 1 END)
AND (CASE WHEN #StateProvince IS NOT NULL THEN StateProvince = #StateProvince ELSE 1 END)
AND (CASE WHEN #TransactionTypeId IS NOT NULL THEN TransactionTypeId = #TransactionTypeId ELSE 1 END)
AND (CASE WHEN #Price IS NOT NULL THEN Price <= #Price ELSE 1 END)
AND IsPublic = 1
AND IsBlocked = 0;
Thanks in advance
If no when conditions are met, case returns null. If you want each test to pass, you need to return a true value instead, so:
case when #price is not null then
price < #price
else 1 end
and ...

SQL Server Row totals in pivot query

I am trying to make a row in the end of the result set that shows the totals.
My query is this:
SELECT
[ ] = ISNULL(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente, 'TOTAL'),
[2016-11-01] = MAX([2016-11-01]),
[2016-11-02] = MAX([2016-11-02]),
[2016-11-03] = MAX([2016-11-03]),
[2016-11-04] = MAX([2016-11-04]),
TOTAL = COUNT([2016-11-01]) + COUNT([2016-11-02]) + COUNT([2016-11-03]) + COUNT([2016-11-04])
FROM
(
SELECT GEN_Paciente.GEN_idPaciente,COALESCE(GEN_ape_paternoPaciente, '')+' '+COALESCE(GEN_ape_maternoPaciente, '')+' '+COALESCE(GEN_nombrePaciente, '') AS nombrePaciente,HOS_fechaCategorizacion,HOS_nivel_riesgoCategorizacion+CAST(HOS_nivel_dependenciaCategorizacion AS VARCHAR) as riesgoDependencia
FROM HOS_Categorizacion
INNER JOIN HOS_Hospitalizacion
ON HOS_Hospitalizacion.HOS_idHospitalizacion = HOS_Categorizacion.HOS_idHospitalizacion
INNER JOIN GEN_Paciente
ON GEN_Paciente.GEN_idPaciente = HOS_Hospitalizacion.GEN_idPaciente
WHERE HOS_nivel_riesgoCategorizacion IS NOT NULL
) src
PIVOT
(
MAX(riesgoDependencia)
for HOS_fechaCategorizacion in ([2016-11-01],[2016-11-02],[2016-11-03],[2016-11-04])
) p
GROUP BY
ROLLUP(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente)
This gives me this result:
But as you can see the totals for the rows are right but the totals for the columns are wrong because I am using MAX instead of COUNT, but I only need COUNT in the TOTAL row, the others have to be MAX, so I wrote this query:
SELECT
[ ] = ISNULL(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente, 'TOTAL'),
[2016-11-01] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-01]) ELSE COUNT([2016-11-01]) END,
[2016-11-02] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-02]) ELSE COUNT([2016-11-02]) END,
[2016-11-03] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-03]) ELSE COUNT([2016-11-03]) END,
[2016-11-04] = CASE WHEN CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente IS NOT NULL THEN MAX([2016-11-04]) ELSE COUNT([2016-11-04]) END,
TOTAL = COUNT([2016-11-01]) + COUNT([2016-11-02]) + COUNT([2016-11-03]) + COUNT([2016-11-04])
FROM
(
SELECT GEN_Paciente.GEN_idPaciente,COALESCE(GEN_ape_paternoPaciente, '')+' '+COALESCE(GEN_ape_maternoPaciente, '')+' '+COALESCE(GEN_nombrePaciente, '') AS nombrePaciente,HOS_fechaCategorizacion,HOS_nivel_riesgoCategorizacion+CAST(HOS_nivel_dependenciaCategorizacion AS VARCHAR) as riesgoDependencia
FROM HOS_Categorizacion
INNER JOIN HOS_Hospitalizacion
ON HOS_Hospitalizacion.HOS_idHospitalizacion = HOS_Categorizacion.HOS_idHospitalizacion
INNER JOIN GEN_Paciente
ON GEN_Paciente.GEN_idPaciente = HOS_Hospitalizacion.GEN_idPaciente
WHERE HOS_nivel_riesgoCategorizacion IS NOT NULL
) src
PIVOT
(
MAX(riesgoDependencia)
for HOS_fechaCategorizacion in ([2016-11-01],[2016-11-02],[2016-11-03],[2016-11-04])
) p
GROUP BY
ROLLUP(CAST(GEN_idPaciente AS VARCHAR)+'-'+nombrePaciente)
But that is not working
Thanks for your help!!
If I understand this correctly you want to count all columns which are not null. In this case you should just look at the condition IS NULL and not at the actual value at all. Try this:
DECLARE #tbl TABLE(ID INT IDENTITY, val1 VARCHAR(100),val2 VARCHAR(100),val3 VARCHAR(100));
INSERT INTO #tbl VALUES
('row1_val1','row1_val2',NULL)
,('row2_val1','row2_val2','row2_val3')
,(NULL,'row2_val2',NULL)
,(NULL,NULL,'row2_val3')
,(NULL,NULL,NULL);
SELECT *
,CASE WHEN val1 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val2 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val3 IS NULL THEN 0 ELSE 1 END AS CountOfValNotNull
FROM #tbl
UPDATE: Add a final Totals Row
You'd need ugly fiddling with a CTE, an additional sort column, UNION ALL to add another row and a sub_select.
Use the outer-most ORDER BY to get the artificial Totals-Row to the end
hint: Use the #tbl variable from above!
WITH SortedRows AS
(
SELECT ROW_NUMBER() OVER(ORDER BY ID) AS SortColumn
,*
,CASE WHEN val1 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val2 IS NULL THEN 0 ELSE 1 END
+CASE WHEN val3 IS NULL THEN 0 ELSE 1 END AS CountOfValNotNull
FROM #tbl
)
SELECT tbl1.*
FROM
(
SELECT * FROM SortedRows
UNION ALL
SELECT 999999,0,'','','',(SELECT SUM(CountOfValNotNull) FROM SortedRows)
) AS tbl1
ORDER BY tbl1.SortColumn

compare one column values with same column values of data in sql server?

ALTER proc [dbo].[K_RT_GetRatebasedonmeat]
#partyname int,
#meattype int
AS
BEGIN
SELECT
CASE WHEN PE.meattype <> (SELECT meattype
FROM K_RT_PartyNameYearly
WHERE partyname = #partyname) THEN 0
ELSE ISNULL(PE.rateperkg, 0)
END AS rateperkg
FROM
K_RT_PartyNameYearly PE
INNER JOIN
K_RT_PartyName PN ON PE.partysno = PN.sno
WHERE
PE.partysno = #partyname
AND PE.meattype = #meattype
END
out put:
PE.partysno PE.meattype PE.rateperkg
36 3 150
36 2 125
25 2 100
if i pass partysno=36 and meattype=1 at that it will show 0 because there is no data for meattype 1 for that partysno
I wrote like this for my requirement but its not working properly. When I pass partyname and meattype as parameters, if K_RT_PartyNameYearly this table does not contain meattype for that partyname at that time I want to show 0 value. How can I write this? Please help me.
TRY THIS...
ALTER proc [dbo].[K_RT_GetRatebasedonmeat]
#partysno int,
#meattype int
AS
BEGIN
if exists
( SELECT 1 FROM K_RT_PartyNameYearly WHERE partysno = #partysno AND meattype = #meattype)
BEGIN
SELECT
PE.partysno ,
PE.meattype,
PE.rateperkg
FROM
K_RT_PartyNameYearly PE
WHERE
PE.partysno = #partysno AND PE.meattype = #meattype
END
ELSE
BEGIN
SELECT distinct
partysno partysno ,
null meattype,
0 AS rateperkg
FROM
K_RT_PartyNameYearly PE
WHERE
PE.partysno = #partysno
END
END

same table count union

SELECT COUNT(*) as totalHappenings FROM `happenings` WHERE `userId` = ?
UNION
SELECT COUNT(*) as xHappenings FROM `happenings` WHERE `userId` = ? AND `destinationObjectType` = \'2\'
UNION
SELECT COUNT(*) as yHappenings FROM `happenings` WHERE `userId` = ? AND `destinationObjectType` = \'1\'
Since it's the same table, and I don't wanna pass through 3 times the userId parameter how can I solve this the best way?
SELECT
COUNT(*) AS totalHappenings,
SUM(CASE WHEN `destinationObjectType` = \'2\' THEN 1 ELSE 0 END) AS xHappenings,
SUM(CASE WHEN `destinationObjectType` = \'1\' THEN 1 ELSE 0 END) AS yHappenings
FROM `happendings`
WHERE `userId` = ?
Result:
totalHappenings xHappenings yHappenings
24 10 14
You can do this with if statements inside select clause:
SELECT
COUNT(userId) as totalHappenings,
SUM(IF(`destinationObjectType`='2',1,0) as xHappenings,
SUM(IF(`destinationObjectType`='1',1,0) as yHappenings
FROM `happenings`
WHERE `userId` = ?
This will surely return your results in 3 columns. Your original query was returning in 3 rows but I think that is not a problem.
try the shortest way:
SELECT COUNT(*) as totalHappenings, SUM(`destinationObjectType` = \'2\') AS xHappenings, SUM(`destinationObjectType` = \'1\') AS yHappenings FROM `happenings` WHERE `userId` = ?
comparision inside SUM returns true or false (1 or 0) so there is no need for IF or CASE statements

SQL ORDER BY query

I want to have my table,rcarddet, ordered by "SDNO" (not primary key) in ascending order with the exception of "0". So it should turn out to be like:
1
1
2
.
.
10
0
0
My query now is:
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
AND `SDNO` != 0
ORDER BY `rcarddet`.`SDNO` ASC;
The easiest way
SELECT * FROM rcarddet
WHERE RDATE = '2011-05-25' and RCNO = '1'and PLACE = 'H'
ORDER BY CASE
WHEN rcarddet.SDNO = 0 THEN [max_number_for_the_type_of_SDNO]
ELSE rcarddet.SDNO
END ASC
SELECT *
FROM `rcarddet`
WHERE `RDATE` = '2011-05-25'
AND `RCNO` = '1'
AND `PLACE` = 'H'
ORDER BY
`SDNO` = 0,
`SDNO`;