【问题标题】:Build customers report of last years with T-SQL使用 T-SQL 构建过去几年的客户报告
【发布时间】:2015-07-02 16:36:32
【问题描述】:

我有 3 张表(简化版):

-----------Orders--------------------
Id | Total_Price | Customer_Id | Date

--------Order Details---------------------
Id | Order_Id | Product Name | Qty | Value

----Customers------
Id | Name | Address

我用这个查询获取单个客户的总订单价值:

SELECT C.ID, C.NAME , SUM(O.TOTAL_PRICE)
FROM CUSTOMERS C
JOIN ORDERS O ON O.CUSTOMER_ID = C.ID
GROUP BY C.ID, C.NAME

现在,我想构建一个包含按日期范围过滤的总订单价值的报告:

SELECT C.ID, C.NAME , SUM(O.TOTAL_PRICE)
FROM CUSTOMERS C
JOIN ORDERS O ON O.CUSTOMER_ID = C.ID
WHERE O.DATE BETWEEN @value1 AND @value2
GROUP BY C.ID, C.NAME

这工作正常,但我想选择按客户分组的最近 3 年总订单价值的总和,这是我想要的结果:

        1Year | 2Year | 3Year | Customer_Name
    ------------------------------------------------- 
        XXX   | YYY   | ZZZZ  | Customer1
        XYX   | YYZ   | ZZTZ  | Customer2
....

我有这个基数: 包含 22.000 行的客户表 包含 87.000 行的订单表 600.000 的订单详情

可以不使用temptable、vartable或存储过程,执行时间长吗?

在我的报告中,我还想计算按产品客户分组的过去 3 年的总数量,但这是下一步。 有任何想法吗? 谢谢

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    您可以使用 case 语句来获得您想要的结果。由于您的帖子中关于如何定义年份范围存在一些歧义,因此我省略了任何计算来获取这些年结束/开始,只是将变量放入其中。您可以根据需要进行修改。

    SELECT C.ID
        ,C.NAME
        ,SUM(CASE 
                WHEN o.DATE BETWEEN @year1start
                        AND @year1end
                    THEN O.TOTAL_PRICE
                ELSE 0
                END) Year1
        ,SUM(CASE 
                WHEN o.DATE BETWEEN @year2start
                        AND @year2end
                    THEN O.TOTAL_PRICE
                ELSE 0
                END) Year2
        ,SUM(CASE 
                WHEN o.DATE BETWEEN @year3start
                        AND @year3end
                    THEN O.TOTAL_PRICE
                ELSE 0
                END) Year3
    FROM CUSTOMERS C
    INNER JOIN ORDERS O ON O.CUSTOMER_ID = C.ID
    GROUP BY C.ID
        ,C.NAME
    

    【讨论】:

      【解决方案2】:

      另一种选择是使用数据透视语句。我假设您的每个日期范围都等于一年(例如 2013 年、2014 年等)。
      如果这些年有强烈的决心,pivot 不是很好的选择(look at full sqlfiddle example, it has possible solution for your additional question):

      select
          c.Id, c.Name, c.Address, CostByYear.[2013], CostByYear.[2014], CostByYear.[2015]
      from Customers c
      left join (
          select
              pt.Customer_Id, isnull(pt.[2013], 0) as [2013], 
              isnull(pt.[2014], 0) as [2014], isnull(pt.[2015], 0) as [2015]
          from (
              select
                  o.Customer_Id, year(o.Date) [Year], sum(o.Total_Price) [TotalCost]
              from Orders o
              group by
                  o.Customer_Id, year(o.Date)
          ) src
          pivot (
              sum(TotalCost) for [Year] in ([2013], [2014], [2015])
          ) pt
      ) CostByYear on
          c.Id = CostByYear.Customer_Id
      order by
          c.Name
      

      如果年份范围未知且未明确定义,您还可以使用动态创建的查询来执行这两种方法(我的答案和上一个答案)。

      【讨论】:

        猜你喜欢
        • 2014-06-18
        • 2012-06-16
        • 2014-09-28
        • 2020-08-30
        • 1970-01-01
        • 2015-07-10
        • 1970-01-01
        • 1970-01-01
        • 2019-04-10
        相关资源
        最近更新 更多