[英]SQL Server Amount Split
我在SQL Server數據庫中有以下2個表。
客戶主要費用表
ReportID CustomerID TotalExpenseAmount
1000 1 200
1001 2 600
與會者表
ReportID AttendeeName
1000 Mark
1000 Sam
1000 Joe
與會者級別沒有金額。 我需要按如下所述手動計算個人出席人數。 (即根據出席人數對TotalExpenseAmount進行拆分,並確保將各個拆分數字四舍五入到小數點后兩位,並精確地總計為TotalExpenseAmount)
最終報告應如下所示:
ReportID CustID AttendeeName TotalAmount AttendeeAmount
1000 1 Mark 200 66.66
1000 1 Sam 200 66.66
1000 1 Joe 200 66.68
最終報告將包含約150,000條記錄。 如果您注意到出席者的數量,我已將最后一位四舍五入,以使總數等於200。在這種情況下,編寫高效SQL查詢的最佳方法是什么?
您可以使用窗口函數執行此操作:
select ReportID, CustID, AttendeeName, TotalAmount,
(case when seqnum = 1
then TotalAmount - perAttendee * (cnt - 1)
else perAttendee
end) as AttendeeAmount
from (select a.ReportID, a.CustID, a.AttendeeName, e.TotalAmount,
row_number() over (partition by reportId order by AttendeeName) as seqnum,
count(*) over (partition by reportId) as cnt,
cast(TotalAmount * 1.0 / count(*) over (partition by reportId) as decimal(10, 2)) as perAttendee
from attendee a join
expense e
on a.ReportID = e.ReportID
) ae;
perAttendee
量是在子查詢中計算的。 這可以通過使用cast()
四舍五入(僅因為floor()
不接受小數位參數)。 對於其中一行,該金額是總值減去所有其他與會者的總和。
做類似於@Gordon的答案,但改用CTE。
with CTECount AS (
select a.ReportId, a.AttendeeName,
ROW_NUMBER() OVER (PARTITION BY A.ReportId ORDER BY A.AttendeeName) [RowNum],
COUNT(A.AttendeeName) OVER (PARTITION BY A.ReportId) [AttendeeCount],
CAST(c.TotalExpenseAmount / (COUNT(A.AttendeeName) OVER (PARTITION BY A.ReportId)) AS DECIMAL(10,2)) [PerAmount]
FROM @Customer C INNER JOIN @Attendee A ON A.ReportId = C.ReportID
)
SELECT CT.ReportID, CT.CustomerId, AT.AttendeeName,
CASE WHEN CC.RowNum = 1 THEN CT.TotalExpenseAmount - CC.PerAmount * (CC.AttendeeCount - 1)
ELSE CC.PerAmount END [AttendeeAmount]
FROM @Customer CT INNER JOIN @Attendee AT
ON CT.ReportID = AT.ReportId
INNER JOIN CTECount CC
ON CC.ReportId = CT.ReportID AND CC.AttendeeName = AT.AttendeeName
我喜歡CTE,因為它使我可以區分查詢的不同方面。 @Gordon使用的很酷的東西是Case語句和內部計算,以使行總數正確。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.