【问题标题】:SQL find average time difference between rows for a given categorySQL查找给定类别的行之间的平均时间差
【发布时间】:2018-01-03 13:29:52
【问题描述】:

我浏览了 SO,但找不到确切的答案,或者可能是针对不同的语言。

假设我有一个表格,其中每一行都是交易记录:

trade_id customer trade_date
1        A        2013-05-01 00:00:00
2        B        2013-05-01 10:00:00    
3        A        2013-05-02 00:00:00
4        A        2013-05-05 00:00:00
5        B        2013-05-06 12:00:00

我想知道交易之间的平均时间,以天数或天数为单位,每个客户,以及自上次交易以来的天数。例如,对于客户 A,交易 1 和 3 之间的时间为 1 天,交易 3 和 4 之间的时间为 3 天,平均为 2。所以最终表看起来像这样(假设今天是 2013-05 -10):

customer avg_time_btw_trades time_since_last_trade
A        2.0                 5.0
B        5.08                3.5

如果客户只有 1 笔交易,我猜 NULL 可以作为输出。

甚至不确定 SQL 是否是执行此操作的最佳方法(我正在使用 SQL 服务器),但感谢您提供任何帮助!

【问题讨论】:

  • @RolandStarke (numberOfTrades - 1)。那么- 1 非常重要,这也意味着你最终想要像NULLIF(numberOfTrades, 1) - 1 这样的东西来避免除以零错误。

标签: sql sql-server datetime group-by


【解决方案1】:
SELECT
  customer,
  DATEDIFF(second, MIN(trade_date), MAX(trade_date)) / (NULLIF(COUNT(*), 1) - 1) / 86400.0,
  DATEDIFF(second, MAX(trade_date), GETDATE()      )                             / 86400.0
FROM
  yourTable
GROUP BY
  customer

http://sqlfiddle.com/#!6/eb46e/7

编辑:添加了我没有注意到的 final 字段,抱歉。

【讨论】:

【解决方案2】:

以下 SQL 脚本使用您的数据并给出预期结果。

DECLARE @temp TABLE
(   trade_id INT,
    customer CHAR(1),
    trade_date DATETIME );
INSERT INTO @temp VALUES (1, 'A', '20130501');
INSERT INTO @temp VALUES (2, 'B', '20130501 10:00');
INSERT INTO @temp VALUES (3, 'A', '20130502');
INSERT INTO @temp VALUES (4, 'A', '20130505');
INSERT INTO @temp VALUES (5, 'B', '20130506 12:00');

DECLARE @getdate DATETIME
-- SET @getdate = getdate();
SET @getdate = '20130510';

SELECT s.customer
    , AVG(s.days_btw_trades) AS avg_time_between_trades
    , CAST(DATEDIFF(hour, MAX(s.trade_date), @getdate) AS float) 
        / 24.0 AS time_since_last_trade
FROM (
    SELECT CAST(DATEDIFF(HOUR, t2.trade_date, t.trade_date) AS float) 
            / 24.0 AS days_btw_trades
        , t.customer
        , t.trade_date
    FROM @temp t
        LEFT JOIN @temp t2 ON t2.customer = t.customer
            AND t2.trade_date = (   SELECT MAX(t3.trade_date)
                                    FROM @temp t3
                                    WHERE t3.customer = t.customer
                                        AND t3.trade_date < t.trade_date)

    ) s
GROUP BY s.customer

【讨论】:

    【解决方案3】:

    您需要每笔交易之间的日期差异并将它们平均。

    select 
    a.customer
    ,avg(datediff(a.trade_date, b.trade_date))
    ,datediff(now(),max(a.trade_date))
    from yourTable a, yourTable b
    where a.customer = b.customer
    and b.trade_date = (
        select max(trade_date) 
        from yourTable c 
        where c.customer = a.customer 
        and a.trade_date > c.trade_date)
        #gets the one earlier date for every trade
    group by a.customer
    

    【讨论】:

      【解决方案4】:

      只是为了笑,我添加了一个使用 CTE 的解决方案。如果第一个查询太大,您可能会使用临时表。我为表格使用了@MatBailie 创建脚本:

      CREATE TABLE customer_trades (
        id            INT IDENTITY(1,1),
        customer_id   INT,
        trade_date    DATETIME,
        PRIMARY KEY (id),
        INDEX ix_user_trades (customer_id, trade_date)
      )
      
      INSERT INTO
        customer_trades (
          customer_id,
          trade_date
        )
      VALUES
        (1, '2013-05-01 00:00:00'),
        (2, '2013-05-01 10:00:00'),
        (1, '2013-05-02 00:00:00'),
        (1, '2013-05-05 00:00:00'),
        (2, '2013-05-06 12:00:00')
      ;
      
      ;WITH CTE as(
      select customer_id, trade_date, datediff(hour,trade_date,ISNULL(LEAD(trade_date,1) over (partition by  customer_id order by trade_date),GETDATE())) Trade_diff
      from customer_trades
      )
      , CTE2 as
      (SELECT customer_id, trade_diff, LAST_VALUE(trade_diff) OVER(Partition by customer_id order by trade_date) Curr_Trade from CTE)
      
      SELECT Customer_id, AVG(trade_diff) AV, Max(Curr_Trade) Curr_Trade
      FROM CTE2
      GROUP BY customer_id
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多