How to use case with in operator - sql-server

Have query like :
declare #case int = 1
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id and a.category in(1,2,3,4,5)
Need when #case = 1 category must be in (1,2,3,4,5), when #case = 2 it must be (1,2,4,5).
Something like this :
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id and (CASE WHEN #case = 1 THEN a.category in(1,2,3,4,5) WHEN #case = 2 THEN (1,2,4,5) ELSE '')
How to do it ?

SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id
and
(
(#case = 1 and a.category in (1,2,3,4,5)) OR
(#case = 2 and a.category in (1,2,4,5))
)
I added parentheses for readability. Not all of them are necessary.

The other answer is better but if you did happen to want to do it with case you could do it like
SELECT a.column1,b.column2
FROM tbl1 a
INNER JOIN tbl2 b on a.id = b.id and
( CASE WHEN #case = 1 and a.category in(1,2,3,4,5) THEN 1
WHEN #case = 2 and a.category in(1,2,3,4) THEN 1
ELSE 0
END
) = 1

Related

Assigning multiple variables in one select

I have the following query:
SELECT
ROW_NUMBER() OVER(ORDER BY A.Price) AS R,
A.Price
FROM
TableA A
INNER JOIN
TableB B ON A.ID = B.ID
INNER JOIN
TableC C ON C.Code = A.Code
WHERE
C.Type = 125
AND A.Desc = 10000038
AND C.YearID = 10000021
GROUP BY
A.Price
This query returns
R
Price
1
165
2
487
3
1807
Is it possible assigning variables #a = 165, #b = 487, and #c = 1807 in one select?
I wrote this query:
WITH P AS (
SELECT
ROW_NUMBER() OVER(ORDER BY A.Price) AS R,
A.Price
FROM
TableA A
INNER JOIN
TableB B ON A.ID = B.ID
INNER JOIN
TableC C ON C.Code = A.Code
WHERE
C.Type = 125
AND A.Desc = 10000038
AND C.YearID = 10000021
GROUP BY
A.Price
)
SELECT
#a = (CASE WHEN [R] = 1 THEN P.[Price] END),
#b = (CASE WHEN [R] = 2 THEN P.[Price] END),
#c = (CASE WHEN [R] = 3 THEN P.[Price] END)
FROM P;
But only #c gets the value.
You need to aggregate. Your query, as it stands, returns 3 rows, which means that the variables are assigned values 3 times as well. What order this is in is arbitrary too, but it might be that #a is first assigned the value 165, then NULL, and then NULL again.
If you aggregate, you can return one row and then the assignments will work as you expect; with each variable being assigned 1 value (not 3):
SELECT #a = MAX(CASE WHEN [R] = 1 THEN P.[Price] END),
#b = MAX(CASE WHEN [R] = 2 THEN P.[Price] END),
#c = MAX(CASE WHEN [R] = 3 THEN P.[Price] END)
FROM P;

Count of insert and update by an employee

i/p
Id Name InsertBy UpdateBy
1 A 2 2
2 B 1 2
3 C 4 3
4 D 4 5
5 E 1 3
O/P(THE COUNT OF EMPLOYEE ID IN INSERT AND COUNT OF EMPID IN UPDATE)
Name InsertBy UpdateBy
A 2 0
B 1 2
C 0 2
D 2 0
E 0 1
It seems to you would require to do self join with separate query (Inserted, Updated) for safer.
SELECT
t.name, a.insertBy, b.updateBy
FROM table t
INNER JOIN
(
SELECT
t.id, count (t1.insertBy) insertBy
FROM table t
LEFT JOIN table t1 on t1.insertBy = t.id
GROUP BY t.id
)a on a.id = t.id
INNER JOIN
(
SELECT
t.id, count (t2.updateBy) updateBy
FROM table t
LEFT JOIN table t2 on t2.updateBy = t.id
GROUP BY t.id
)b on b.id = t.id
Let me edit with other approach which more efficient with separate join
select t1.name, sum(case when a.Name = 'InsertedBy' then 1 else 0 end) InsertBy,
sum(case when a.Name = 'UpdatedBy' then 1 else 0 end) UpdateBy
from table t
cross apply (
values (InsertBy, 'InsertedBy'), (UpdateBy, 'UpdatedBy')
)a(Types, Name)
LEFT JOIN table t1 on t1.Id = a.Types
group by t1.name
However, these will make use of index on (Id)

Number of execution is equal to the number of rows in SQL Server

I am having a query in which number of execution is equal to the number of rows in the table.
Anyone knows any possible reason for that as a result the clustered index seek %age is very high.
I have update the Stats for the Tables.But still no benefit.
select #AdditionalBillToNumericValue = cast(ab_vnum as int) from #table1
inner join table4 on ab_btid = ay_bt and ab_type = 'SRVGRP'
if(#AdditionalBillToNumericValue is not null or #AdditionalBillToNumericValue <> '')
begin
select distinct
fs.sv_pkey
, fs.sv_id
, fs.sv_desc
,ISNULL( fs.sv_ehr,0) as sv_ehr
,ISNULL( fs.sv_emn,0) as sv_emn
,ISNULL( fs.sv_lhr,0) as sv_lhr
,ISNULL( fs.sv_lmn,0) as sv_lmn
,(case when #table1.fh_sv = fs.sv_id then 1 else 0 end) IsDefault
from table3 fr
inner join table4 ab on ab.ab_vnum = fr.sr_sgpkey
inner join table5 fs on fr.sr_svpkey = fs.sv_pkey or fs.sv_pkey = #ServiceWindowKey
inner join #table1 on ab.ab_btid = #table1.ay_bt
AND ab.ab_type = 'SRVGRP'
end
else
begin
select
fs.sv_pkey
, fs.sv_id
, fs.sv_desc
,ISNULL(sv_ehr,0) as sv_ehr
,ISNULL(sv_emn,0) as sv_emn
,ISNULL(sv_lhr,0) as sv_lhr
,ISNULL(sv_lmn,0) as sv_lmn
,(case when #table1.fh_sv = fs.sv_id then 1 else 0 end) IsDefault
from table3 fr
inner join table4 ab on ab.ab_vnum = fr.sr_sgpkey
inner join table5 fs on fr.sr_svpkey = fs.sv_pkey or fs.sv_pkey = #ServiceWindowKey
LEFT join #table1 with(nolock) on ab.ab_btid = #table1.ay_bt
where ab.ab_type = 'SRVGRP'
Please Verify where we are having the join with table5 it is getting the issue.
In Join Both are having int datatype.

SQL Query tuning - MS SQL Server -2012

I am new to sql tuning. I have the following SQL which takes around 15 to 20 seconds to produce the results.
SELECT D.DealerName,
Z.Zone,
C.Id ,
L.Id ,
A.Id ,
L.LeadDate,
LT.LeadType ,
EM.FirstName + ' ' + EM.LastName ,
LS.LeadSource ,
--C.*,
E.Id ,
E.StartDateTime,
0 ,
Chiefed = CASE A.AppointmentTypeId
WHEN 3 THEN 'True'
ELSE ''
END,
9 AS WorkflowPhase
FROM Customers C( NOLOCK )
INNER JOIN Dealers D
ON C.DEALERId = D.Id
INNER JOIN Leads L( NOLOCK )
ON L.CustomerId = C.Id
INNER JOIN Appointments A( NOLOCK )
ON A.LeadId = L.Id
AND ( NOT( A.AppointmentTypeId = 5
OR A.AppointmentTypeId = 6 ) )
JOIN CalendarEvents E( NOLOCK )
ON E.TableId = 1
AND E.TableRowId = A.Id
AND E.IsDeleted = 0
AND Dateadd(hh, #TZO, Getdate()) >= E.StartDateTime
LEFT OUTER JOIN AppointmentResults AR( NOLOCK )
ON AR.EventId = E.Id
LEFT OUTER JOIN LeadSources LS( NOLOCK )
ON LS.Id = L.LeadSourceId
LEFT OUTER JOIN LeadTypes LT( NOLOCK )
ON LT.Id = L.LeadTypeId
LEFT OUTER JOIN Users EM( NOLOCK )
ON EM.Id = E.EmployeeId
LEFT OUTER JOIN Zone Z( NOLOCK )
ON Z.Id = C.ZoneId
WHERE EXISTS(SELECT 1
FROM WorkflowStatus WS( NOLOCK )
WHERE TableId = 1
AND TableRowId = A.Id
AND WorkflowPhaseId = 9
AND IsCompleted = 0
AND IsDeleted = 0)
AND ( EXISTS (SELECT 1
FROM dbo.Uft_userpermissionzonesbyworkflow(#EmployeeId, 9)
WHERE ZoneId = C.zoneid) )
AND EXISTS (SELECT 1
FROM Uft_userenableddealers(#EmployeeId)
WHERE DealerId = C.DealerId)
ORDER BY C.LastName,
C.CompanyName,
C.CompanyContact
I already tuned up to my knowledge but still I can see some index scans. I tried to convert those index scans to index seek but it is not possible due to number of records.
Please refer the screenshot of plan diagram and top operations
Kindly provide any suggestions to improvise this query.
DECLARE #p TABLE (DealerId INT PRIMARY KEY WITH (IGNORE_DUP_KEY=ON))
INSERT INTO #p
SELECT DealerId
FROM dbo.Uft_userenableddealers(#EmployeeId)
DECLARE #z TABLE (ZoneId INT PRIMARY KEY WITH (IGNORE_DUP_KEY=ON))
INSERT INTO #z
SELECT ZoneId
FROM dbo.Uft_userpermissionzonesbyworkflow(#EmployeeId, 9)
SELECT ...
FROM ...
WHERE EXISTS(SELECT 1
FROM WorkflowStatus WS( NOLOCK )
WHERE TableId = 1
AND TableRowId = A.Id
AND WorkflowPhaseId = 9
AND IsCompleted = 0
AND IsDeleted = 0)
AND C.zoneid IN (SELECT * FROM #z)
AND C.DealerId IN (SELECT * FROM #p)
ORDER BY C.LastName,
C.CompanyName,
C.CompanyContact
OPTION(RECOMPILE)
as discussed below Devarts answer here the example with a CTE instead of the declared table variables. I'd assume that the declared TVs are faster due to the key, but the CTE is ad-hoc and - maybe - better integrated. Thx for testing:
;WITH p AS
(
SELECT DealerId
FROM dbo.Uft_userenableddealers(#EmployeeId)
)
,z AS
(
SELECT ZoneId
FROM dbo.Uft_userpermissionzonesbyworkflow(#EmployeeId, 9)
)
SELECT ...
FROM ...
WHERE EXISTS(SELECT 1
FROM WorkflowStatus WS( NOLOCK )
WHERE TableId = 1
AND TableRowId = A.Id
AND WorkflowPhaseId = 9
AND IsCompleted = 0
AND IsDeleted = 0)
AND C.zoneid IN (SELECT ZoneId FROM z)
AND C.DealerId IN (SELECT DealerId FROM p)
ORDER BY C.LastName,
C.CompanyName,
C.CompanyContact
OPTION(RECOMPILE)

SQL Conditional calculations

I have 3 tables. They have 1 to many relations
table1 - mainID, Select00(bit), Select01(bit)
table2 - secID, mainID
table3 - secID, Num00, Num01
SELECT table1.mainID , SUM(table3.Num00) as S00, SUM(table3.Num01) as S01
FROM table1 INNER JOIN
table2 ON table1.mainID = table2.mainID INNER JOIN
table3 ON table2.secID = table3.secID
GROUP BY table1.mainID HAVING table1.mainID =11
The following query works, but gives me all sums.
How do I get the SUMs based on condition? i.e
S00 = SUM(table3.Num00) if table1.Select00 = 1 (true)
S01 = SUM(table3.Num01) if table1.Select01 = 1 (true)
SELECT
t1.mainID,
S00 = SUM(CASE WHEN t1.Select00 = 1 THEN t3.Num00 ELSE 0 END),
S01 = SUM(CASE WHEN t1.Select01 = 1 THEN t3.Num01 ELSE 0 END)
FROM
dbo.table1 AS t1
INNER JOIN dbo.table2 AS t2
ON t1.mainID = t2.mainID
INNER JOIN dbo.table3 AS t3
ON t2.secID = t3.secID
WHERE t1.MainID = 11
GROUP BY table1.mainID;

Resources