2015-12-24 46 views
2

我在SQL Server数据库中有2个以下的表。SQL Server数量拆分

客户主要费用表

ReportID CustomerID TotalExpenseAmount 
1000  1   200 
1001  2   600 

参加者表

ReportID AttendeeName 
1000  Mark 
1000  Sam 
1000  Joe 

有一个在与会者级别没有量。我需要手动计算个人参与者数量,如下所述。 (即基于分裂TotalExpenseAmount在与会者的数量,并确保各个分割的数字轮2位小数,准确地总结到TotalExpenseAmount)

最终报告应该是这样的:

ReportID CustID AttendeeName TotalAmount AttendeeAmount 
1000  1  Mark   200   66.66 
1000  1  Sam   200   66.66 
1000  1  Joe   200   66.68 

的最终报告将拥有约1,50,000条记录。如果您注意到与会者的数量,我已经以总数匹配到200的方式舍入了最后一个。在这种情况下编写高效的SQL查询的最佳方式是什么?

回答

0

做一些类似于@ 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语句和内部计算来使行正确地总计。

+0

你太棒了。感谢你能这么快回复!!! –

3

为此,您可以使用窗口函数:

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()不接受小数位参数)向下舍入。对于其中一行,金额是总和减去所有其他与会者的总和。