简体   繁体   English

SQL 用于计算 mtd、ytd 值的查询

[英]SQL query for calculating mtd, ytd values

I have a table with columns ID , Title , Date , Amount .我有一个包含IDTitleDateAmount列的表。

I need to get MTD, YTD amount values against each transaction based on Title , Date .我需要根据TitleDate获取每笔交易的 MTD、YTD 金额值。

Is there anyone who had done this before?有没有人以前做过这个?

Select t.title, t.Date, 
  Sum(y.Amount) YTD,
  Sum(m.Amount) MTD
From table t
   join table y
      on y.Title = t.Title
         and datediff(year, y.Date, t.Date) = 0 
         and y.Date <= t.Date
   join table m
      on m.Title = t.Title
         and datediff(month, m.Date, t.Date) = 0 
         and m.Date <= t.Date
Group by t.title, t.Date
SELECT ID,
       Title,
       Date,
       Amount,
       MTD  = SUM(Amount) OVER (PARTITION BY Title, DATEADD(MONTH, DATEDIFF(MONTH, 0, [Date]), 0)),
       YTD  = SUM(Amount) OVER (PARTITION BY Title, DATEADD(YEAR, DATEDIFF(YEAR, 0, [Date]), 0))
FROM   [a_table]

The accepted solution is incorrect.接受的解决方案是不正确的。 Let's say we have a following table:假设我们有一个下表:

ID   Title   Date        Amount
---  ------  ----------  ------
  1  Cust A  2020-01-01    2.00
  2  Cust A  2020-01-05    3.00
  3  Cust A  2020-02-01    5.00

The accepted answer would give us these results:接受的答案会给我们这些结果:

Title   Date        YTD    MTD
------  ----------  -----  -----
Cust A  2021-01-01   2.00   2.00
Cust A  2021-01-05  10.00  10.00
Cust A  2021-02-01  10.00  15.00

This is due to the fact that each join multiplies the number of records by the number of matching records.这是因为每个连接都将记录数乘以匹配记录数。 This can be easily seen when the aggregation is removed:当聚合被移除时,这可以很容易地看到:

Select t.title, t.Date, y.Date, m.Date,
  y.Amount,
  m.Amount
From [table] t
   join [table] y
      on y.Title = t.Title
         and datediff(year, y.Date, t.Date) = 0 
         and y.Date <= t.Date
   join [table] m
      on m.Title = t.Title
         and datediff(month, m.Date, t.Date) = 0 
         and m.Date <= t.Date
Order by t.title, t.Date, y.Date, m.Date

Results:结果:

Title   t.Date      y.Date      m.Date      y.Amount    m.Amount
-----   ----------  ----------  ----------  --------    --------
Cust A  2021-01-01  2021-01-01  2021-01-01         2           2
Cust A  2021-01-05  2021-01-01  2021-01-01         2           2
Cust A  2021-01-05  2021-01-01  2021-01-05         2           3
Cust A  2021-01-05  2021-01-05  2021-01-01         3           2
Cust A  2021-01-05  2021-01-05  2021-01-05         3           3
Cust A  2021-02-01  2021-01-01  2021-02-01         2           5
Cust A  2021-02-01  2021-01-05  2021-02-01         3           5
Cust A  2021-02-01  2021-02-01  2021-02-01         5           5

Here is a modified select that produces correct results:这是一个产生正确结果的修改后的选择:

Select a.title, a.Date, 
  Sum(Case When datediff(year, b.Date, a.Date) = 0 Then b.Amount Else 0 End) YTD,
  Sum(Case When datediff(month, b.Date, a.Date) = 0 Then b.Amount Else 0 End) MTD
From [table] a
   join [table] b
      on a.Title = b.Title
         and b.Date <= a.Date
Group by a.title, a.Date

Results:结果:

Title   Date        YTD    MTD
------  ----------  -----  -----
Cust A  2021-01-01   2.00   2.00
Cust A  2021-01-05   5.00   5.00
Cust A  2021-02-01  10.00   5.00

Here is a SQL Fiddle with all the current answers plus new solutions.这是一个包含所有当前答案以及新解决方案的SQL Fiddle

Another solution by using Cross Apply :使用Cross Apply的另一种解决方案:

see this sqlfiddle看到这个sqlfiddle

CREATE TABLE [table] (
  ID int IDENTITY(1,1) PRIMARY KEY,
  Title nvarchar(20),
  Date date,
  Amount money
)

INSERT INTO [table] (Title, Date, Amount)
VALUES ('Cust A', '2021-01-01', 2.00),
       ('Cust A', '2021-01-05', 3.00),
       ('Cust A', '2021-02-05', 4.00),
       ('Cust A', '2021-02-06', 5.00),
       ('Cust B', '2021-01-01', 20.00),
       ('Cust B', '2021-01-05', 30.00),
       ('Cust B', '2021-02-05', 40.00),
       ('Cust B', '2021-02-06', 50.00);
       
SELECT t1.title
      ,t1.Date
      ,t1.Amount
      ,t2.Amount_YTD
      ,t3.Amount_MTD
FROM [table] t1
     CROSS APPLY
(
    SELECT SUM(Amount) AS Amount_YTD
    FROM [table] t2
    WHERE t2.Date <= t1.Date
          AND t1.Title = t2.Title
          AND datediff(year, t1.Date, t2.Date) = 0 
) t2
     CROSS APPLY
(
    SELECT SUM(Amount) AS Amount_MTD
    FROM [table] t3
    WHERE t3.Date <= t1.Date
          AND t1.Title = t3.Title
          AND datediff(month, t1.Date, t3.Date) = 0 
) t3

what if we have only one table how can we execute如果我们只有一张桌子怎么办?

for instance Select status, r_date, Sum(Case When datediff(year, r_date) = 0 Then hours Else 0 End) YTD, Sum(Case When datediff(month, r_date) = 0 Then hours Else 0 End) MTD From table 1 Group by status,r_date例如 Select status, r_date, Sum(Case When datediff(year, r_date) = 0 Then hours Else 0 End) YTD, Sum(Case When datediff(month, r_date) = 0 Then hours Else 0 End) MTD From table 1 Group按状态,r_date

while running above query getting me an error could you please help me to get it Thanks在运行上面的查询时出现错误,你能帮我得到它吗谢谢

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM