Sql server SQL-计算时间差的平均值

Sql server SQL-计算时间差的平均值,sql-server,Sql Server,我有一个sql表,其中包含所有客户端的事务历史记录。我想知道两次交易的平均时间差是多少 ClientCode Date DL2xxx 2016-04-18 00:00:00.000 DL2xxx 2016-04-18 00:00:00.000 E19xxx 2016-04-18 00:00:00.000 E19xxx 2016-04-18 00:00:00.000 E19xxx 2016-04-1

我有一个sql表,其中包含所有客户端的事务历史记录。我想知道两次交易的平均时间差是多少

ClientCode      Date
DL2xxx          2016-04-18 00:00:00.000
DL2xxx          2016-04-18 00:00:00.000
E19xxx          2016-04-18 00:00:00.000
E19xxx          2016-04-18 00:00:00.000
E19xxx          2016-04-18 00:00:00.000
JDZxxx          2016-04-18 00:00:00.000
上面给出的是表格的前几行,给出的日期是事务发生的日期。我想取连续交易发生时天数的平均差值。假设客户在第1天、第3天、第10天和第15天进行交易。所以差异是{2,7,5},平均值是4.66。如果仅发生一个事务,则该值应为0

ClientCode AverageDays
DL2xxx     <float_value>
DL2xxx     <float_value>
E19xxx     <float_value>
ClientCode平均天数
DL2xxx
DL2xxx
E19xxx
这就是每个唯一的客户端代码只出现一次时输出的样子。

您可以使用
LAG()
函数按客户端将日期与其上一个日期进行比较,然后按客户端分组并计算平均值

IF OBJECT_ID('tempdb..#Transactions') IS NOT NULL
    DROP TABLE #Transactions

CREATE TABLE #Transactions (
    ClientCode VARCHAR(100),
    Date DATE)

INSERT INTO #Transactions (
    ClientCode,
    Date)
VALUES
    ('DL2', '2016-04-18'),
    ('DL2', '2016-04-19'),
    ('DL2', '2016-04-26'),

    ('E19', '2016-01-01'),
    ('E19', '2016-01-11'),
    ('E19', '2016-01-12')


;WITH DayDifferences AS
(
    SELECT
        T.ClientCode,
        T.Date,
        DayDifference = DATEDIFF(
            DAY,
            LAG(T.Date) OVER (PARTITION BY T.ClientCode ORDER BY T.Date ASC),
            T.Date)
    FROM
        #Transactions AS T
)
SELECT
    D.ClientCode,
    AverageDayDifference = AVG(ISNULL(CONVERT(FLOAT, D.DayDifference), 0))
FROM
    DayDifferences AS D
GROUP BY
    D.ClientCode
您可以使用
LAG()
函数按客户端将日期与其上一个日期进行比较,然后按客户端分组并计算平均值

IF OBJECT_ID('tempdb..#Transactions') IS NOT NULL
    DROP TABLE #Transactions

CREATE TABLE #Transactions (
    ClientCode VARCHAR(100),
    Date DATE)

INSERT INTO #Transactions (
    ClientCode,
    Date)
VALUES
    ('DL2', '2016-04-18'),
    ('DL2', '2016-04-19'),
    ('DL2', '2016-04-26'),

    ('E19', '2016-01-01'),
    ('E19', '2016-01-11'),
    ('E19', '2016-01-12')


;WITH DayDifferences AS
(
    SELECT
        T.ClientCode,
        T.Date,
        DayDifference = DATEDIFF(
            DAY,
            LAG(T.Date) OVER (PARTITION BY T.ClientCode ORDER BY T.Date ASC),
            T.Date)
    FROM
        #Transactions AS T
)
SELECT
    D.ClientCode,
    AverageDayDifference = AVG(ISNULL(CONVERT(FLOAT, D.DayDifference), 0))
FROM
    DayDifferences AS D
GROUP BY
    D.ClientCode

如果表名为T,则可以使用如下查询


如果表名为T,则可以使用如下查询


如果您无法使用窗口功能,这里有一种替代方法

--CREATE SAMPLE DATA
CREATE TABLE #TMP(ClientID INT, EventDate DATE)
GO

INSERT INTO #TMP VALUES
(1,DATEADD(DD,RAND()*365,'20180101'))
,(2,DATEADD(DD,RAND()*365,'20180101'))
,(3,DATEADD(DD,RAND()*365,'20180101'))
,(4,DATEADD(DD,RAND()*365,'20180101'))
,(5,DATEADD(DD,RAND()*365,'20180101'))
GO 50


--PRE SQL 2012 Compatible
SELECT A.ClientID
        ,AVG(DATEDIFF(DD,C.EventDate,A.Eventdate)) AS ClientAvg

 FROM #TMP A
    CROSS APPLY (SELECT ClientID, MAX(EventDate) EventDate FROM #TMP B
                    WHERE A.ClientID = B.ClientID AND A.EventDate > B.EventDate
                    GROUP BY ClientID) C
GROUP BY A.ClientID
ORDER BY A.ClientID

如果您无法使用窗口功能,这里有一种替代方法

--CREATE SAMPLE DATA
CREATE TABLE #TMP(ClientID INT, EventDate DATE)
GO

INSERT INTO #TMP VALUES
(1,DATEADD(DD,RAND()*365,'20180101'))
,(2,DATEADD(DD,RAND()*365,'20180101'))
,(3,DATEADD(DD,RAND()*365,'20180101'))
,(4,DATEADD(DD,RAND()*365,'20180101'))
,(5,DATEADD(DD,RAND()*365,'20180101'))
GO 50


--PRE SQL 2012 Compatible
SELECT A.ClientID
        ,AVG(DATEDIFF(DD,C.EventDate,A.Eventdate)) AS ClientAvg

 FROM #TMP A
    CROSS APPLY (SELECT ClientID, MAX(EventDate) EventDate FROM #TMP B
                    WHERE A.ClientID = B.ClientID AND A.EventDate > B.EventDate
                    GROUP BY ClientID) C
GROUP BY A.ClientID
ORDER BY A.ClientID

通过观察组内的差异总和就是该组的
max-min
,您可以通过选择以下选项使用简单组:

select IIF(COUNT(*) > 1, 
(CAST(DATEDIFF(day, MIN(DateofT), MAX(DateofT)) AS FLOAT)) / (COUNT(*) - 1), 0.0) 
AS AVGDays, ClientCode 
FROM t GROUP BY ClientCode

通过观察组内的差异总和就是该组的
max-min
,您可以通过选择以下选项使用简单组:

select IIF(COUNT(*) > 1, 
(CAST(DATEDIFF(day, MIN(DateofT), MAX(DateofT)) AS FLOAT)) / (COUNT(*) - 1), 0.0) 
AS AVGDays, ClientCode 
FROM t GROUP BY ClientCode

您是否可以添加示例输出和输入数据?我添加了更多详细信息。如果您发现这不足,请通知我。如果性能是一个问题,您能否提供表中有哪些索引的信息?哪些是索引?此表中没有唯一标识符。表的其余部分包含交易价值、税收、产品、数量等。您是否可以添加样本输出和输入数据?我已经添加了更多详细信息。如果您认为这不够充分,请通知我。如果性能是一个问题,您能否提供表中有哪些索引的信息?哪些是索引?此表中没有唯一标识符。表的其余部分包含交易、税收、产品、数量等的价值。因此,这将创建一个日差查询,然后从该表中获取平均值,对吗?在你和dhruvjoshi的答案中,这是一个更快的答案,因为我必须在非常大的范围内运行它table@PiyushDivyanakar这两个查询是相似的,应该产生相似的性能。您可能希望在运行之前在ClientCode、Date上创建一个索引。因此,这将创建一个DayDifference查询,然后从该表中获取平均值,对吗?在你和dhruvjoshi的答案中,这是一个更快的答案,因为我必须在非常大的范围内运行它table@PiyushDivyanakar这两个查询是相似的,应该产生相似的性能。您可能希望在运行之前在ClientCode、Date上创建一个索引。如果只有一个事务,这会给$0$吗?如果只有一个事务,这会给$0$?