计算订单之间的平均天数

Za*_*hir 4 sql-server t-sql sql-server-2014

我想从一个名为 Orders 的表中计算几个订单日期之间的平均天数。对于每个 CustomerID,订单之间的平均天数是多少。示例表如下(img):

CREATE TABLE #Orders(CustomerID int, OrderDate datetime);

INSERT #Orders(CustomerID, OrderDate) VALUES
    (100,'20170114'),(100,'20170123'),(100,'20170129'),
    (101,'20170202'),(101,'20170212');
Run Code Online (Sandbox Code Playgroud)

我试过这个查询:

SELECT  CustomerID, AVG(OrderDate - PriorDate)
FROM (SELECT CustomerID, OrderDate
           , LAG(OrderDate) OVER (PARTITION BY CustomerID ORDER BY OrderDate) as PriorDate
      FROM #Orders where CustomerID = 100)
Run Code Online (Sandbox Code Playgroud)

但是,这会产生:

消息 102,级别 15,状态 1
')' 附近的语法不正确。

Aar*_*and 6

几个问题:

  • 您试图取每个客户的平均值,但您没有按客户分组。
  • datetimes( OrderDate-PriorDate) 的隐式数学不是一个好主意(尝试使用 date 或 datetime2) - 使用DATEDIFF
  • 整数除法不会像你想象的那样给你一个平均值 - 试试SELECT 5/2;。您需要将至少一个输入转换为小数,隐式 ( *1.0) 或显式 ( CONVERT(), TRY_CONVERT(), CAST(), etc.)。Explicit 允许您在某些情况下控制小数位。
  • LAG() 未完成 - 虽然默认值为 1,但我认为最好明确表示您想要前一行。
  • 不正确的语法错误实际上来自查询的末尾 - 当您有类似的内容时SELECT ... FROM (<subquery>),该子查询需要命名,因此您需要使用类似SELECT ... FROM (<subquery>) AS x;的内容。

请尝试以下操作:

SELECT 
  CustomerID, 
  AvgLag = AVG(CONVERT(decimal(7,2), DATEDIFF(DAY, PriorDate, OrderDate)))
FROM
(
  SELECT CustomerID, OrderDate, PriorDate = LAG(OrderDate,1) 
    OVER (PARTITION BY CustomerID ORDER BY OrderDate)
  FROM #Orders
  WHERE CustomerID = 100
) AS lagged
GROUP BY CustomerID;
Run Code Online (Sandbox Code Playgroud)

结果:

CustomerID    AvgLag
----------    ------
100           7.50
Run Code Online (Sandbox Code Playgroud)

当然,如果您想要所有客户的平均值,只需省略该WHERE条款。但是,如果您真的只想要一个客户,那么您实际上并不需要输出中的客户,因此您可以稍微调整查询以摆脱GROUP BY(让我们在处理时参数化客户 ID) :

DECLARE @CustomerID int = 100;

SELECT AvgLag = AVG(Lag), CustomerID = @CustomerID -- you may not need this
FROM 
(
  SELECT Lag = CONVERT(decimal(7,2), DATEDIFF(DAY, LAG(OrderDate,1) 
    OVER (PARTITION BY CustomerID ORDER BY OrderDate), OrderDate))
  FROM #Orders
  WHERE CustomerID = @CustomerID
) AS Lagged;
Run Code Online (Sandbox Code Playgroud)


ype*_*eᵀᴹ 5

一种简化查询的方法 - 如果您只需要订单日期之间的平均滞后时间 - 是确定您只需要第一个和最后一个订单的日期以及每个客户的订单数量。如果您有 11 个客户的订单,并且第一个订单和最后一个订单之间有一年的时间,则平均值为365 / 10.

SELECT 
  CustomerID, 
  AvgLag = CASE WHEN COUNT(*) > 1 THEN 
                    CONVERT(decimal(7,2), 
                            DATEDIFF(day, MIN(OrderDate), MAX(OrderDate)))
                    / CONVERT(decimal(7,2), COUNT(*) - 1)
                ELSE NULL
           END
FROM #Orders
GROUP BY CustomerID ;
Run Code Online (Sandbox Code Playgroud)