按日期总计加上运行总计

时间:2019-11-13 17:10:34

标签: sql-server tsql

我有一个订单表,每行都有:

  • 订单ID
  • 订单签出日期
  • 订单交易价值

我希望按日期(yyyy-mm-dd)对该期间的交易值进行分组,但我也想返回该期间的运行总额。如果我针对这几个月的数据(到11月的13天)运行此查询,那么我期望看到返回的结果集

  • 13行,每月的每一天一次,
  • 当月某天的交易值
  • 到目前为止该月的运行总计

我可以使用分组依据获取交易值分组依据日期,但没有运行总计。如果我在分区上使用 ,则每笔交易我将获得1行,但当天的交易价值之和。

当前代码如下:

SELECT 
    left(convert(varchar(30),OrderCheckOutDate,120),10), 
    SUM (OrderTotalFixed) 
    OVER (Partition By left(convert(varchar(30),OrderCheckOutDate,120),10))
FROM 
    tblOrder
Where
    UserExternalUserLevel = 0 
And
    OrderCheckOutDate > '2019-11-01'

好像查询正在按毫秒进行分区,但我认为转换将处理此问题?

3 个答案:

答案 0 :(得分:2)

要按日期分组,您不需要OVER (Partition By)并将该列放在“分组依据”下

尝试一下:

;WITH TotalByDay AS (
SELECT 
    convert(DATE,OrderCheckOutDate) OrderCheckOutDate ,
    SUM (OrderTotalFixed) OrderTotalFixed 
FROM 
    tblOrder
Where
    UserExternalUserLevel = 0 
And
    OrderCheckOutDate > '2019-11-01'
GROUP BY  convert(DATE,OrderCheckOutDate)
)

SELECT 
   OrderCheckOutDate,
   (SELECT SUM(TotalByDay) FROM TotalByDay innerT where innerT.OrderCheckOutDate <= T.OrderCheckOutDate) RunningTotal
FROM TotalByDay t
GROUP BY t.OrderCheckOutDate

答案 1 :(得分:2)

与其他示例相比,这里的版本缩小了代码的大小。它也应该比某些方法快一点,因为没有子查询会强制多次读取表。使用运行总计和group by语句时要记住的技巧是,您不将window函数应用于原始列,而是应用于原始列的汇总(因此我将SUM嵌套在SUM中)。

SELECT 
    CAST(OrderCheckOutDate AS date) AS OrderCheckOutDate, 
    SUM (OrderTotalFixed) AS DayTotal,
    SUM (SUM (OrderTotalFixed)) OVER (ORDER BY CAST(OrderCheckOutDate AS date)) AS RunningTotal
FROM 
    tblOrder
Where
    UserExternalUserLevel = 0 
And
    OrderCheckOutDate > '2019-11-01'
GROUP BY CAST(OrderCheckOutDate AS date)

您可以在dbfiddle

上看到此功能

例如,如果您的实际用例更加复杂,则您希望每个月重置运行总额,可以通过将PARTITION添加到窗口函数中来处理。

按月分区将如下所示:

SELECT 
    CAST(OrderCheckOutDate AS date) AS OrderCheckOutDate,
    EOMONTH(CAST(OrderCheckOutDate AS date)) AS MonthEnd,
    SUM (OrderTotalFixed) AS DayTotal,
     SUM (SUM (OrderTotalFixed)) OVER (PARTITION BY EOMONTH(CAST(OrderCheckOutDate AS date)) ORDER BY CAST(OrderCheckOutDate AS date) ) AS RunningTotal
FROM 
    tblOrder
Where
    UserExternalUserLevel = 0 
And
    OrderCheckOutDate > '2019-11-01'
GROUP BY CAST(OrderCheckOutDate AS date)

再一次看到它与dbfiddle一起起作用

答案 2 :(得分:1)

这是我做过的类似事情,希望您可以根据自己的餐桌/需求进行调整。 内部查询(TOTALS_Q)仅按月获取销售和计数。 外部查询也会获取累计值。

累加的重要部分是“未绑定的行和当前行之间的行”

SELECT 
  SaleMonth, Month_Order_Count, MonthTotal,   
  SUM(Month_Order_Count) OVER(ORDER BY SaleMonth ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Cumulative_Order_Count,
  SUM(MonthTotal) OVER(ORDER BY SaleMonth ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Cumulative_Order_Value
FROM 
(
  SELECT SUB_Q.SaleMonth, Count( DISTINCT SUB_Q.OrderID) as Month_Order_Count, SUM(Value) as MonthTotal  FROM
  (
    SELECT CONCAT( DatePart( year, OH.OrderDate), '-', FORMAT( OH.OrderDate, 'MM')) as SaleMonth,
    OI.OrderID,
    OI.Value
  FROM ORDERHEADER OH 
  INNER JOIN OrderItem OI ON OI.OrderID = OH.OrderID
  INNER JOIN ECodeOrder ECO ON ECO.OrderId = OH.ORDERID
  INNER JOIN Product P ON P.ProductId = OI.ProductId AND P.Denomination >= 10000
  ) SUB_Q
  GROUP BY SUB_Q.SaleMonth
)TOTALS_Q
ORDER BY SaleMonth