簡體   English   中英

SQL Server金額拆分

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM