【问题标题】:Joining next Sequential Row加入下一个连续行
【发布时间】:2014-10-15 11:46:34
【问题描述】:

我现在正在计划一个 SQL 语句,需要有人来看看我的想法。

这是我的桌子:

id  stat    period
--- ------- --------
1   10      1/1/2008
2   25      2/1/2008
3    5      3/1/2008
4   15      4/1/2008
5   30      5/1/2008
6    9      6/1/2008
7   22      7/1/2008
8   29      8/1/2008

创建表

CREATE TABLE tbstats
  (
     id     INT IDENTITY(1, 1) PRIMARY KEY,
     stat   INT NOT NULL,
     period DATETIME NOT NULL
  )

go

INSERT INTO tbstats
            (stat,period)
SELECT 10,CONVERT(DATETIME, '20080101')
UNION ALL
SELECT 25,CONVERT(DATETIME, '20080102')
UNION ALL
SELECT 5,CONVERT(DATETIME, '20080103')
UNION ALL
SELECT 15,CONVERT(DATETIME, '20080104')
UNION ALL
SELECT 30,CONVERT(DATETIME, '20080105')
UNION ALL
SELECT 9,CONVERT(DATETIME, '20080106')
UNION ALL
SELECT 22,CONVERT(DATETIME, '20080107')
UNION ALL
SELECT 29,CONVERT(DATETIME, '20080108')

go 

我想计算每个统计量与下一个统计量之间的差异,然后计算“差距”的平均值。

想法:

我需要将每条记录与其后续行连接起来。我可以使用更灵活的连接语法来做到这一点,这要归功于我知道 id 字段是一个没有间隙的整数序列。

通过给表加上别名,我​​可以将它合并到 SQL 查询中两次,然后通过将第一个别名表的 id 加 1 以交错的方式将它们连接在一起。表中的第一条记录的 id 为 1。1 + 1 = 2 因此它应该加入第二个别名表中 id 为 2 的行。等等。

现在我将简单地从另一个中减去一个。

然后我会使用 ABS 函数来确保我总是得到正整数作为减法的结果,而不管表达式的哪一侧是较高的数字。

有没有更简单的方法来实现我想要的?

【问题讨论】:

    标签: sql sql-server join union


    【解决方案1】:

    lead 分析函数应该可以解决问题:

    SELECT period, stat, stat - LEAD(stat) OVER (ORDER BY period) AS gap
    FROM   tbstats
    

    【讨论】:

    • 对不起,我没有在我的问题中提到 SQl 服务器版本,虽然这可能适用于较新的版本,但它不适合我
    【解决方案2】:

    间隙的平均值可以通过计算第一个值和最后一个值之间的差值并除以元素数减去一个来完成:

    select sum(case when seqnum = num then stat else - stat end) / (max(num) - 1);
    from (select period, row_number() over (order by period) as seqnum,
                 count(*) over () as num
          from tbstats
         ) t
    where seqnum = num or seqnum = 1;
    

    当然,您也可以使用lead() 进行计算,但这也适用于 SQL Server 2005 和 2008。

    【讨论】:

    • 这是完美的。谢谢
    【解决方案3】:

    通过使用 Join 也可以实现这一目标

    SELECT t1.period,
           t1.stat,
           t1.stat - t2.stat gap
    FROM   #tbstats t1
           LEFT JOIN #tbstats t2
                  ON t1.id + 1 = t2.id 
    

    【讨论】:

      【解决方案4】:

      要计算每个统计数据与下一个统计数据之间的差异,LEAD() and LAG() 可能是最简单的选项。您提供ORDER BY,LEAD(something) 返回下一个 something,LAG(something) 返回前一个 something 按照给定的顺序。

      select
        x.id thisStatId,
        LAG(x.id) OVER (ORDER BY x.id) lastStatId,
        x.stat thisStatValue,
        LAG(x.stat) OVER (ORDER BY x.id) lastStatValue,
        x.stat - LAG(x.stat) OVER (ORDER BY x.id) diff
      from tbStats x
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-27
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多