[英]How can I simplify the sql query?
我有以下查詢,它在具有大量數據的 sql 服務器中不起作用。 當我在 where 子句中使用具有 3 個組合的日期過濾器時,查詢不起作用。
IF OBJECT_ID('tempdb..#tempAllocStatus1') IS NOT NULL
DROP TABLE #tempAllocStatus1
SELECT Users.Name,REPLACE(Staff.Designation, 'IND ', '') as Designation, Staff.Office as Location,
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.AssignedToID = Users.UserADID AND Req.TypeOfRequest = 1 AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENRE' or ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRR' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF'))) [Indian Benchmarking Assigned],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.ReviewerID = Users.UserADID AND Req.TypeOfRequest = 1 AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF' or SubStatusCode='RPC' or SubStatusCode='TPRPC'))) [Indian Benchmarking Reviewer],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.SignoffID = Users.UserADID AND Req.TypeOfRequest = 1 AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='RPSOFF' or ReqDt.SubStatusCode='SCPC' or ReqDt.SubStatusCode='TPSCPC'))) [Indian Benchmarking Signoff],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.AssignedToID = Users.UserADID AND Req.TypeOfRequest = 1 AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENRE' or ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRR' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF'))) +
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.ReviewerID = Users.UserADID AND Req.TypeOfRequest = 1 AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF' or SubStatusCode='RPC' or SubStatusCode='TPRPC'))) +
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.SignoffID = Users.UserADID AND Req.TypeOfRequest = 1 AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='RPSOFF' or ReqDt.SubStatusCode='SCPC' or ReqDt.SubStatusCode='TPSCPC'))) [Indian Benchmarking Total],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
WHERE ReqDt.AssignedToID = Users.UserADID AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENRE' or ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRR' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF'))) [All Assigned],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
WHERE ReqDt.ReviewerID = Users.UserADID AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF' or SubStatusCode='RPC' or SubStatusCode='TPRPC'))) [All Reviewer],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.SignoffID = Users.UserADID AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='RPSOFF' or ReqDt.SubStatusCode='SCPC' or ReqDt.SubStatusCode='TPSCPC'))) [All Signoff],
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
WHERE ReqDt.AssignedToID = Users.UserADID AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENRE' or ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRR' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF'))) +
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
WHERE ReqDt.ReviewerID = Users.UserADID AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='BENSF' or ReqDt.SubStatusCode='DRSO' or ReqDt.SubStatusCode='RPSOFF' or SubStatusCode='RPC' or SubStatusCode='TPRPC'))) +
(SELECT COUNT(ReqDt.ID) FROM tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req ON ReqDt.RequestID = Req.Id
WHERE ReqDt.SignoffID = Users.UserADID AND ((ReqDt.StatusCode = 'COMP' or ReqDt.StatusCode = 'PCR') or (ReqDt.StatusCode = 'AWIP' and ReqDt.SubStatusCode='RPSOFF' or ReqDt.SubStatusCode='SCPC' or ReqDt.SubStatusCode='TPSCPC'))) [All Total]
INTO #tempAllocStatus1
FROM tblUserRolesMapping Users
LEFT JOIN [tblstaff] Staff ON Users.UserADID = Staff.AD_Id
LEFT JOIN tblTPRequestDetail UserAssigned ON UserAssigned.AssignedToID = Users.UserADID
LEFT JOIN tblTPRequestDetail UserReviewer ON UserReviewer.ReviewerID = Users.UserADID
LEFT JOIN tblTPRequestDetail UserSignoff ON UserSignoff.SignoffID = Users.UserADID
LEFT JOIN tblTPRequest TPRAssigned ON UserAssigned.RequestID = TPRAssigned.ID
LEFT JOIN tblTPRequest TPRReviewer ON UserReviewer.RequestID = TPRReviewer.ID
LEFT JOIN tblTPRequest TPRSignoff ON UserSignoff.RequestID = TPRSignoff.ID
WHERE Users.Active = 1 and Users.[RoleId] !=6
AND (TPRAssigned.crtddate >= '2017-04-01' and TPRAssigned.crtddate<= '2017-05-30')
OR (TPRReviewer.crtddate >= '2017-04-01' AND TPRReviewer.crtddate<='2017-05-30')
OR (TPRSignoff.crtddate >= '2017-04-01' AND TPRSignoff.crtddate<='2017-05-30' )
GROUP BY Users.UserADID, Users.Name, Staff.Designation,Staff.Office
SELECT * FROM #tempAllocStatus1 WHERE [All Total] > 0
UNION ALL
SELECT * FROM #tempAllocStatus1 WHERE [All Total] = 0
我在下面的查詢行中遇到了這個問題。
AND (TPRAssigned.crtddate >= '2017-04-01' and TPRAssigned.crtddate<= '2017-05-30')
OR (TPRReviewer.crtddate >= '2017-04-01' AND TPRReviewer.crtddate<='2017-05-30')
OR (TPRSignoff.crtddate >= '2017-04-01' AND TPRSignoff.crtddate<='2017-05-30')
我嘗試了許多解決方案來簡化此查詢。 但是沒有任何東西可以處理大量數據。 它正在處理很長時間並獲得超時執行。 任何人都可以幫助簡化這個查詢嗎?
根據建議,我已優化查詢如下。
select
ReqDt.AssignedToID,
COUNT(*) NumRecs
into
#tmpAssigned
from
tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req
ON ReqDt.RequestID = Req.Id
AND Req.TypeOfRequest = 1
AND Req.crtddate >= '2017-04-01'
and Req.crtddate <= '2022-05-30'
WHERE
ReqDt.StatusCode IN ( 'COMP', 'PCR' )
OR ( ReqDt.StatusCode = 'AWIP'
and ReqDt.SubStatusCode IN ( 'BENRE', 'BENSF', 'DRR', 'DRSO', 'RPSOFF' )
)
GROUP BY
ReqDt.AssignedToID
select
ReqDt.ReviewerID,
COUNT(*) NumRecs
into
#tmpReviewed
from
tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req
ON ReqDt.RequestID = Req.Id
AND Req.TypeOfRequest = 1
AND Req.crtddate >= '2017-04-01'
and Req.crtddate <= '2022-05-30'
WHERE
ReqDt.StatusCode IN ( 'COMP', 'PCR' )
OR ( ReqDt.StatusCode = 'AWIP'
and ReqDt.SubStatusCode IN ( 'BENSF', 'DRSO', 'RPSOFF', 'RPC', 'TPRPC' )
)
GROUP BY
ReqDt.ReviewerID
select
ReqDt.SignoffID,
COUNT(*) NumRecs
into
#tmpSigned
from
tblTPRequestDetail ReqDt
INNER JOIN tblTPRequest Req
ON ReqDt.RequestID = Req.Id
AND Req.TypeOfRequest = 1
AND Req.crtddate >= '2017-04-01'
and Req.crtddate <= '2022-05-30'
WHERE
ReqDt.StatusCode IN ( 'COMP', 'PCR' )
OR ( ReqDt.StatusCode = 'AWIP'
and ReqDt.SubStatusCode IN ( 'RPSOFF', 'SCPC', 'TPSCPC' )
)
GROUP BY
ReqDt.SignoffID
SELECT U.Name,
REPLACE(S.Designation, 'IND ', '') as Designation,
S.Office as Location,
coalesce( Assigned.NumRecs, 0 ) [Indian Benchmarking Assigned],
coalesce( Reviewed.NumRecs, 0 ) [Indian Benchmarking Reviewed],
coalesce( Signed.NumRecs, 0 ) [Indian Benchmarking Signed],
coalesce( Assigned.NumRecs, 0 ) + coalesce( Reviewed.NumRecs, 0 ) + coalesce( Signed.NumRecs, 0 ) [total Indian Benchmarking]
from
tblUserRolesMapping U
left JOIN [tblstaff] S
ON U.UserADID = S.AD_Id
left JOIN #tmpAssigned Assigned
on U.UserADID = Assigned.AssignedToID
left JOIN #tmpReviewed Reviewed
on U.UserADID = Reviewed.ReviewerID
left JOIN #tmpSigned Signed
on U.UserADID = Signed.SignoffID
WHERE
U.Active = 1
and U.RoleId !=6
and coalesce( Assigned.NumRecs, 0 ) + coalesce( Reviewed.NumRecs, 0 ) + coalesce( Signed.NumRecs, 0 ) !=0
order by U.Name
但我得到了重復的記錄。 如何從結果中刪除重復記錄。 此外,具有 USERADID 的同一用戶可以在 tblUserRoleMapping 表中擁有多個角色。
顯然是多余的,但還要考慮您的 where 條件,尤其是在您的計數查詢中。 查看您的(StatusCode 和 SubStatusCode 或 SubStatusCode 或 SubStatusCode 或...)。 如果您隨后的任何 OR 條件為真,則將被視為真。 查看 StatusCode = 'AWIP' 和 SubStatus = 'DRSO',這將被解釋為
( true and false or false or true or false ) resulting in TRUE
或另一個查看 StatusCode = 'XYZ' 和 SubStatus = 'DRSO',這將被解釋為
( false and false or false or true or false ) resulting in TRUE.
我認為您要完成的是(分別根據上面的示例
( true and (false or false or true or false )) resulting in TRUE
( false and (false or false or true or false )) resulting in FALSE.
您希望主要狀態代碼 = 'AWIP' 的位置,如果是這樣,則僅在任何 SUBSTATUS 代碼是以下任何一個時才計算在內。 如果這是有意的,您的括號不能正確容納。 通過更改為 IN () 子句可以幫助簡化這種歧義。
現在,通過重復,如果這是預先編寫為子查詢,按用戶 ID 分組並獲取您可以加入一次的計數
由於您已經在 SQL-Server 中使用“#”臨時表,因此您可以預先查詢這些結果,然后在沒有用戶 ID 的情況下再次 sum() 每個類別的總計。
根據重復 STAFF 的評論,您需要獲取唯一的 STAFF ID(未提供,因此我將整理列名。您顯然可以調整它)。 此外,由於傳遞關聯(如果 a=b 和 b=c 則 a=c),我將加入 STAFF 表並獲得 STAFF 唯一 ID。 此外,通過刪除“角色”的上下文,我還為 StaffUserName 創建了一個列。 這將消除重復記錄,因為它匯總了每個人的總數,而不是每個人的角色。
select
S.UniqueStaffID,
COUNT(*) NumRecs
into
#tmpAssigned
from
tblTPRequestDetail ReqDt
JOIN [tblstaff] S
ON ReqDt.AssignedToID = S.AD_Id
INNER JOIN tblTPRequest Req
ON ReqDt.RequestID = Req.Id
AND Req.TypeOfRequest = 1
-- apply the date filters directly to where you are getting queries
AND Req.crtddate >= '2017-04-01'
and Req.crtddate <= '2017-05-30'
WHERE
-- and only getting same criteria
ReqDt.StatusCode IN ( 'COMP', 'PCR' )
OR ( ReqDt.StatusCode = 'AWIP'
and ReqDt.SubStatusCode IN ( 'BENRE', 'BENSF', 'DRR', 'DRSO', 'RPSOFF' )
)
GROUP BY
S.UniqueStaffID
select
S.UniqueStaffID,
COUNT(*) NumRecs
into
#tmpReviewed
from
tblTPRequestDetail ReqDt
JOIN [tblstaff] S
ON ReqDt.AssignedToID = S.AD_Id
INNER JOIN tblTPRequest Req
ON ReqDt.RequestID = Req.Id
AND Req.TypeOfRequest = 1
-- apply the date filters directly to where you are getting queries
AND Req.crtddate >= '2017-04-01'
and Req.crtddate <= '2017-05-30'
WHERE
-- and only getting same criteria
ReqDt.StatusCode IN ( 'COMP', 'PCR' )
OR ( ReqDt.StatusCode = 'AWIP'
and ReqDt.SubStatusCode IN ( 'BENSF', 'DRSO', 'RPSOFF', 'RPC', 'TPRPC' )
)
GROUP BY
S.UniqueStaffID
select
S.UniqueStaffID,
COUNT(*) NumRecs
into
#tmpSigned
from
tblTPRequestDetail ReqDt
JOIN [tblstaff] S
ON ReqDt.AssignedToID = S.AD_Id
INNER JOIN tblTPRequest Req
ON ReqDt.RequestID = Req.Id
AND Req.TypeOfRequest = 1
-- apply the date filters directly to where you are getting queries
AND Req.crtddate >= '2017-04-01'
and Req.crtddate <= '2017-05-30'
WHERE
-- and only getting same criteria
ReqDt.StatusCode IN ( 'COMP', 'PCR' )
OR ( ReqDt.StatusCode = 'AWIP'
and ReqDt.SubStatusCode IN ( 'RPSOFF', 'SCPC', 'TPSCPC' )
)
GROUP BY
S.UniqueStaffID
SELECT
S.StaffUserName,
REPLACE(S.Designation, 'IND ', '') as Designation,
S.Office as Location,
coalesce( Assigned.NumRecs, 0 ) [Indian Benchmarking Assigned],
coalesce( Reviewed.NumRecs, 0 ) [Indian Benchmarking Reviewed],
coalesce( Signed.NumRecs, 0 ) [Indian Benchmarking Signed],
coalesce( AllAssigned.NumRecs, 0 ) [All Indian Benchmarking Assigned],
coalesce( AllReviewed.NumRecs, 0 ) [All Indian Benchmarking Reviewed],
coalesce( AllSigned.NumRecs, 0 ) [All Indian Benchmarking Signed],
coalesce( AllAssigned.NumRecs, 0 )
+ coalesce( AllReviewed.NumRecs, 0 )
+ coalesce( AllSigned.NumRecs, 0 ) [AllRecords]
from
JOIN [tblstaff] S
LEFT JOIN #tmpAssigned Assigned
on S.UniqueStaffID = Assigned.UniqueStaffID
JOIN
( select sum(NumRecs) NumRecs
from #tmpAssigned ) AllAssigned
on 1=1
LEFT JOIN #tmpReviewed Reviewed
on S.UniqueStaffID = Reviewed.UniqueStaffID
JOIN
( select sum(NumRecs) NumRecs
from #tmpReviewed ) AllReviewed
on 1=1
LEFT JOIN #tmpSigned Signed
on S.UniqueStaffID = Signed.UniqueStaffID
JOIN
( select sum(NumRecs) NumRecs
from #tmpSigned ) AllSigned
on 1=1
WHERE
U.Active = 1
and U.RoleId !=6
ORDER BY
S.StaffUserName,
S.Designation,
S.Office
由於 Assigned、Reviewed 和 Signed 的預查詢一次最多預聚合到一條用戶記錄,因此您無需在外層使用 group by。 此外,對於已分配、已審核、已簽名的“總計”,由於這些未分組,它們將始終是代表各個類別的整個合格記錄池的單個記錄。 應該可以幫助您完成查詢並在嘗試時進行總計。
根據評論反饋更新。
我的查詢中沒有使用任何“不同”,您必須添加它。 至於為什么,我只能假設一個用戶ROLE ID可能關聯多個Staff? 如果您可以編輯您的原始帖子並分享一些代表此類角色和員工的樣本數據可能會有所幫助(並做幾個角色/員工以查看更好的相關性,顯然沒有真正的私人/機密)。 這可能是多條記錄的來源。
我的印象是“UserADID”是唯一用戶,而不是用戶角色,因為此 ID 已分配給請求詳細信息。 我只能猜測影響,但現在我想你可能有類似的東西
ApprovingRole ID = 1
Office 1 Staff person ID X
Office 2 Staff Person ID Y
Office 3 Staff Person ID Z
ReviewingRole ID = 2
Office 2 Staff person ID A
Office 2 Staff Person ID Y
Office 4 Staff person ID B
SigningRole ID = 3
Office 2 Staff Person ID Y
Office 4 Staff person ID B
在上面的“示例數據”中,您可以看到員工“Y”是所有 3 個角色的成員。 工作人員“B”是2個角色的成員。
etc
那么這里真正處理的是哪個“ID”。 批准“角色”ID 1 是與請求詳細信息相關聯,還是與員工 X、Y、Z 相關聯。
如果數據與我所擁有的一樣,並且由於您缺乏樣本數據,我怎么知道與哪個員工站點/指定相關的基礎計數。 總計代表 ROLD 用戶 ID,而不是 STAFF 用戶 ID。 否則請告訴我,我可以編輯結果。
所以現在你 state 有相同的用戶重復,而不是用戶角色,在這種情況下。 我們需要將每個預查詢 temp 一直連接到 USER STAFF ID。 不是角色 ID。 我已經修改了上面的查詢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.