在SQL查询中每年选择SUM

时间:2014-09-24 02:14:45

标签: sql sql-server

我有这两个表:

费用表

id           expense      expense_date                     product_id

1              10           2012-01-03                       1

2              10           2014-02-01                       2

3              10           2014-02-03                       1

4              10           2012-07-03                       1 

产品表

product_id                product_name             purchase_date

 1                            car                    2010-02-01

 2                           bike                    2014-03-01

我希望通过将费用分组与product_id相加来实现结果这样的结果,其中expense_date介于purchase_date与明年之间:

Year        Expense         Product_name      

 1             0                 car                 2010-02-01 to 2011-02-01

 2            10                 car                 2011-02-01 to 2012-02-01

 3            10                 car                 2012-02-01 to 2013-02-01

 4             0                 car                 2013-02-01 to 2014-02-01

 5            10                 car                 2014-02-01 to 2015-02-01               

 1            10                 bike                2014-03-01 to 2015-03-01

2 个答案:

答案 0 :(得分:3)

CREATE VIEW dbo.vwMaxExpenseDate
AS 
    SELECT product_id, MAX(expense_date) AS 'max_expense_date'
    FROM Expense
    GROUP BY product_id

DECLARE @PossibleYearRange TABLE
(
    product_id INT,
    YearStart DATETIME,
    YearEnd DATETIME
);

WITH CTE
AS
(
    SELECT p.product_id, max_expense_date, purchase_date, 1 As Number
    FROM Product p
    LEFT JOIN vwMaxExpenseDate e
    ON p.product_id = e.product_id

    UNION ALL

    SELECT product_id, max_expense_date, purchase_date, Number + 1
    FROM CTE
    WHERE Number <= (YEAR(max_expense_date) - YEAR(purchase_date)) 
)
INSERT INTO @PossibleYearRange
(
    product_id,
    YearStart,
    YearEnd
)
SELECT product_id, 
        CONVERT(DATETIME, CONVERT(VARCHAR(20), YEAR(purchase_date) + Number - 1) + '-' 
            + CONVERT(VARCHAR(20), MONTH(purchase_date)) + '-' 
            + CONVERT(VARCHAR(20), DAY(purchase_date))) AS 'YearStart',
        CONVERT(DATETIME, CONVERT(VARCHAR(20), YEAR(purchase_date) + Number) + '-' 
            + CONVERT(VARCHAR(20), MONTH(purchase_date)) + '-' 
            + CONVERT(VARCHAR(20), DAY(purchase_date))) AS 'YearEnd'
FROM CTE
ORDER BY product_id ASC, NUMBER ASC

SELECT MAX(p.product_id) AS product_id, MAX(product_name) AS product_name, YearStart, YearEnd, COALESCE(SUM(expense), 0) AS TotalExpensePerYear
FROM @PossibleYearRange p
LEFT JOIN Expense e
ON p.product_id = e.product_id AND
expense_date BETWEEN YearStart AND YearEnd
INNER JOIN Product d 
ON p.product_id = d.product_id
GROUP BY YearStart, YearEnd
ORDER BY MAX(p.product_id) ASC

希望这有帮助!感谢。

答案 1 :(得分:1)

declare @BeginsAt as datetime
declare @numOf as int

set @BeginsAt = (select min(purchase_date) from Products)
set @BeginsAt  = dateadd(year,datediff(year,0,@BeginsAt),0) -- force to 1st of Year

set @numOf = (year(getdate()) - year(@BeginsAt))+1

;with YearRange (id, StartAt, StopAt)
as (
    select 1 as id, @BeginsAt, dateadd(Year,1,@BeginsAt)
    union all
    select (id + 1) , dateadd(Year,1,StartAt) , dateadd(Year,1,StopAt)
    from YearRange
    where (id + 1) <= @numOf
    )
select
        y.id
      , coalesce(e.expense,0)  expense
      , p.product_name
      , y.startAt
      , dateadd(day,-1,y.StopAt)
from YearRange Y
left join Products P on Y.StopAt between P.purchase_date AND (select max(StopAt) from YearRange)
left join Expenses E on E.expense_date >= Y.StartAt and E.expense_date < Y.StopAt
                     and E.product_id = P.product_id

See this SQLFiddle demo