SQL查找给定类别的行之间的平均时间差

问题描述 投票:0回答:4

我浏览了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服务器),但任何帮助表示赞赏!

sql sql-server datetime group-by
4个回答
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

编辑:添加了我没有注意到的最终字段,道歉。


0
投票

以下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

0
投票

您需要在每笔交易之间存在日期差异并对其进行平均。

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

0
投票

只是为了笑容,我添加了一个使用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
© www.soinside.com 2019 - 2024. All rights reserved.