SQL simplifying case in case in case - sql

I got the following SQL code (part of a select Statement):
Case
When HilfsTab2.Gruppe = 'HST' And Basis.Breite_FLA = Basis.Breite Then 0
Else Case When HilfsTab2.Gruppe = 'SA' Or HilfsTab2.Gruppe = 'HO / TB' Or
HilfsTab2.Gruppe = 'PR' Then 0 Else Case
When HilfsTab2.Gruppe Is Null Then -1 Else 1 End End
End As IsHST_Fluegel
Now, I run this over a table of several million entries. From my understanding, SQL checks the first case when for all rows, then the second for all entries and so on. This takes ages. Now I was thinking, there needs to be an easier way to do this.
I was thinking of a stored procedure / custom function that basically outputs -1, 0 or 1 depending on the entry.
Thanks in advance

For a possible speed improvement, do the NULL check first, the column comparison last and refactor to remove the nested CASE:
CASE WHEN HilfsTab2.Gruppe IS NULL
THEN -1
WHEN HilfsTab2.Gruppe IN ('SA', 'HO / TB', 'PR')
OR (HilfsTab2.Gruppe = 'HST' AND Basis.Breite_FLA = Basis.Breite)
THEN 0
ELSE 1
END AS IsHST_Fluegel

Your case could be simplified as:
Case
When HilfsTab2.Gruppe = 'HST' And Basis.Breite_FLA = Basis.Breite Then 0
When HilfsTab2.Gruppe in ('SA', 'HO / TB', 'PR') Then 0
When HilfsTab2.Gruppe Is Null Then -1
Else 1
End As IsHST_Fluegel
But this will not speed up your query. If you want to select millions of rows, it would take time anyway.

Related

Using CASE statement name as another reference filed in another CASE statement

Is it possible to refer to another case statement name in another case statement within SQL query?
Example: I have 3 case statements. The first 2 case statements are returning values based off coded fields. My 3rd case statement I would like to refer to the ending case name to return a sum of quantity.
However, I cannot figure how to get the case statement to refer to the previous case names I created. I hope I am explaining this correctly.
Any assistance would be greatly appreciated. Please see attached image for more detail.
SELECT CI_ITEM.ITEMCODE
, CI_ITEM.ITEMCODEDESC
, CASE WHEN DATEDIFF("M",CI_ITEM.DATECREATED,GETDATE()) <60 THEN DATEDIFF("M",CI_ITEM.DATECREATED,GETDATE())
ELSE 60 END AS NO_OF_MONTHS
, CASE WHEN DATEDIFF("M",IM_ITEMTRANSACTIONHISTORY.TRANSACTIONDATE,GETDATE()) <=60
AND IM_ITEMTRANSACTIONHISTORY.TRANSACTIONCODE IN ('BI','II','SO','WI')
THEN IM_ITEMTRANSACTIONHISTORY.TRANSACTIONQTY *-1 ELSE '0' END AS QTY_CONSUMED_60_MONTHS
, CASE WHEN NO_OF_MONTHS = 0 THEN 0 ELSE SUM([QTY_CONSUMED_60_MONTHS])/ [NO_OF_MONTHS] END AS MONTHLY_AVE_ON_60MONTHS_DATA
FROM CI_ITEM
INNER JOIN IM_ITEMTRANSACTIONHISTORY ON CI_ITEM.ITEMCODE = IM_ITEMTRANSACTIONHISTORY.ITEMCODE
Simply wrap your dependent cases within a sub query and reference them as fields of the sub query result.
SELECT
*,
CASE WHEN NO_OF_MONTHS = 0 THEN 0 ELSE SUM([QTY_CONSUMED_60_MONTHS])/ [NO_OF_MONTHS] END AS MONTHLY_AVE_ON_60MONTHS_DATA
FROM
(
SELECT CI_ITEM.ITEMCODE
, CI_ITEM.ITEMCODEDESC
, CASE WHEN DATEDIFF("M",CI_ITEM.DATECREATED,GETDATE()) <60 THEN DATEDIFF("M",CI_ITEM.DATECREATED,GETDATE())
ELSE 60 END AS NO_OF_MONTHS
, CASE WHEN DATEDIFF("M",IM_ITEMTRANSACTIONHISTORY.TRANSACTIONDATE,GETDATE()) <=60
AND IM_ITEMTRANSACTIONHISTORY.TRANSACTIONCODE IN ('BI','II','SO','WI')
THEN IM_ITEMTRANSACTIONHISTORY.TRANSACTIONQTY *-1 ELSE '0' END AS QTY_CONSUMED_60_MONTHS
FROM CI_ITEM
INNER JOIN IM_ITEMTRANSACTIONHISTORY ON CI_ITEM.ITEMCODE = IM_ITEMTRANSACTIONHISTORY.ITEMCODE
)AS X

case statement in where clause SQLSERVER

I tried searching around but couldn't find anything that would help me out.
I'm trying to do this in SQL:
DECLARE #onlyMM INT
SET #onlyMM = 1
SELECT *
FROM cdn.magnag
WHERE CASE #onlyMM
WHEN 1
THEN man_zrdtyp NOT IN (
1616
,2001
)
ELSE - 1
END
I have a problem with:
where case #onlyMM when 1 then man_zrdtyp not in (1616,2001) else -1 end
how to properly make a case for the operator not in?
I think you need to formulate the WHERE clause in a different way. You could use OR instead of case statement. Like this:
WHERE
(#onlyMM=1 AND man_zrdtyp not in (1616,2001))
OR #onlyMM<>1
You don't want to do this?
where (case when #onlyMM = 1 then man_zrdtyp else -1 end) not in (1616,2001)

Get work time in minutes based on shift schedule

In production we have 3 shifts. Each Shift timing is described in table tbl_ShiftSched:
WT - work time, PT - break time.
ShiftTmID - schedule for 2 and for 3 shifts.
I am looking for easy way to get work time in minutes having start and end time.
For example, having input between #2015.05.29 06:10:00# and #2015.05.29 09:30:00# and tbl_WorkStations.WksID='GRD' (Workstation code with relation on ShiftTmID ='3P') should give output 190 min.
I have function in MS Access which gives me needed output. But when migrated to T-SQL it becomes very complicated because I do not find easy way how to use alias in T-SQL. Here is the code:
USE [STRDAT]
GO
declare
#strWks varchar(3),
#dteIN datetime='2013.08.05 03:30',
#dteOUT datetime='2013.08.05 05:30',
#strShf varchar(12)=null,--'2013.08.04-3',
#strInd varchar(2) = 'WT',
#dteFTm datetime,
#dteShf date
--#PrdS datetime,
--#PrdE datetime
select top 1
#dteFTm =
case
when #strShf is not null
then (select shiftstart from tbl_ShiftSched where ShiftTmID=(select ShiftTiming from tbl_WorkStations where WksID=#strWks) and shift=right(#strshf,1) and sortind=1)
else #dteIN-dateadd(day,datediff(day,0,#dteIN),0) --CAST(#dteIN-cast(floor(#dteIN) as float) as datetime)
end,
#dteShf=
case
when #strShf is not null
then left(#strShf,10)
else convert(varchar,dateadd(day,datediff(day,0,#dteIN),0),102)
end
--select #dteftm,#dteShf
SELECT tbl_ShiftSched.Shift,
tbl_ShiftSched.SortInd,
[ShiftStart]+
case
when #dteFTm>[shiftstart]
then DateAdd(day,1,#dteShf)
else #dteShf
end AS PrdS,
[ShiftEnd]+
case
when #dteFTm>[shiftend]
then DateAdd(day,1,#dteShf)
else #dteShf
end AS PrdE,
case
when #dteIN>=[PrdS] AND [PrdE]>=#dteOUT
then DateDiff(minute,#dteIN,#dteOUT)
else case
when #dteIN<=[PrdS] AND [PrdE]<=#dteOUT
then DateDiff(minute,[PrdS],[PrdE])
else case
when [PrdS]<=#dteIN AND #dteIN<=[PrdE]
then DateDiff(minute,#dteIN,[Prde])
else case
when [PrdS]<=#dteOUT AND #dteOUT<=[PrdE]
then DateDiff(minute,[Prds],#dteOUT)
else 0
end
end
end
end AS Tm,
#dteIN AS S,
#dteOUT AS E,
tbl_ShiftSched.ShiftType,tbl_ShiftSched.ShiftStart,tbl_ShiftSched.ShiftEnd
FROM tbl_WorkStations
INNER JOIN tbl_ShiftSched ON tbl_WorkStations.ShiftTiming = tbl_ShiftSched.ShiftTmID
WHERE (((tbl_WorkStations.WksID)=#strWks))
Off course it gives me an error Invalid column name 'PrdS' and 'PrdE' because I use alias.
Must be some more easy way to achieve it. Maybe I am on wrong direction?...
Whenever I have to calculate a field and use the results in a second field, I use a common table expression to make the first calculation. Given this query, it could look like this:
with cte_preprocess as
(
SELECT tbl_ShiftSched.Shift,
tbl_ShiftSched.SortInd,
[ShiftStart]+
case
when #dteFTm>[shiftstart]
then DateAdd(day,1,#dteShf)
else #dteShf
end AS PrdS,
[ShiftEnd]+
case
when #dteFTm>[shiftend]
then DateAdd(day,1,#dteShf)
else #dteShf
end AS PrdE,
tbl_ShiftSched.ShiftType,tbl_ShiftSched.ShiftStart,tbl_ShiftSched.ShiftEnd
FROM tbl_WorkStations
INNER JOIN tbl_ShiftSched ON tbl_WorkStations.ShiftTiming = tbl_ShiftSched.ShiftTmID
WHERE (((tbl_WorkStations.WksID)=#strWks))
)
SELECT [Shift]
, SortInd
, PrdS
, PrdE
, case
when #dteIN>=[PrdS] AND [PrdE]>=#dteOUT
then DateDiff(minute,#dteIN,#dteOUT)
else case
when #dteIN<=[PrdS] AND [PrdE]<=#dteOUT
then DateDiff(minute,[PrdS],[PrdE])
else case
when [PrdS]<=#dteIN AND #dteIN<=[PrdE]
then DateDiff(minute,#dteIN,[Prde])
else case
when [PrdS]<=#dteOUT AND #dteOUT<=[PrdE]
then DateDiff(minute,[Prds],#dteOUT)
else 0
end
end
end
end AS Tm
, #dteIN
, #dteOUT
, ShiftEnd
FROM cte_preprocess
More on CTE's here

Using CASE WHEN in a WHERE Statement to return ALL records if #parameter = 0

I am using Visual Studio 2008 and am in a report trying to create a query that has a WHERE statement that will return all records, if the #parameter = 0, otherwise I want the query to return only records that have the #paramete.
Here is the statement I envision, but can't seem to get correct:
WHERE (ADVISOR.staffPersonID = CASE WHEN #advisor = 0 THEN **'Do NOT
filter by staffpersonID'** ELSE #advisor END)
I have tried the following code which doesn't work:
CASE WHEN #advisor = 0 THEN ADVISOR.staffPersonID ELSE #advisor END
ADVISOR.staffPersonID is the field I would filter on, if the #parameter had a value other than 0. From what I've researched online, using the field itself as the THEN in the statement should work. It does, unless the table (advisor) has no records that match in it at all.
WHERE
(#advisor <> 0 AND ADVISOR.staffPersonID = #advisor)
OR
(#advisor = 0 )
try this:
WHERE ADVISOR.staffPersonID = #advisor OR #advisor = 0
WHERE ((ADVISOR.staffPersonID IS NULL AND #advisor = 0) 
OR (ADVISOR.staffPersonID  = CASE WHEN #advisor = 0 THEN 
ADVISOR.staffPersonID 
ELSE 
#advisor END
))

IIF to CASE WHEN statement

Good day.. Im having a hard time in converting from ms access sql to sql server 2005 sql query.. and here's my code :
UPDATE Data SET
Data.Mean =([std1]+[std2]+[std3]/
IIf((3+(([std1]=0)+([std2]=0)+([std3]=0)))>0,
(3+(([std1]=0)+([std2]=0)+([std3]=0))),1)
WHERE Data.ID=125
I think the best way to convert this is by using CASE WHEN STATEMENT or any suggestions/alternatives you already know?
Thank you in advance!
Try this
UPDATE Data SET
Mean =([std1]+[std2]+[std3])/
case when abs([std1])+abs([std2])+abs([std3])=0 then 1 else
3 + case [std1] when 0 then -1 else 0 end
+ case [std2] when 0 then -1 else 0 end
+ case [std3] when 0 then -1 else 0 end
end
WHERE ID=125
UPDATE Data SET
Data.Mean =([std1]+[std2]+[std3]/
(CASE WHEN (3+(([std1]=0)+([std2]=0)+([std3]=0)))>0
THEN (3+(([std1]=0)+([std2]=0)+([std3]=0)))
ELSE 1
END))
WHERE Data.ID=125