【问题标题】:SQL difference between rows行之间的 SQL 差异
【发布时间】:2011-06-11 12:13:46
【问题描述】:

我有一个这样的 SQL 2008 数据库表

name      score
-----------------------
steve     207
steve     205
steve     200
steve     139

我想得到行之间的差异。 eqn = [行 - (行 + 1)] 所以我希望它是理想的,

steve 2   //207 - 205
steve 5   //205 - 200
steve 61  //200 - 139
steve 139 //139 - 0

最好的方法是什么? 谢谢!

【问题讨论】:

  • 巧妙的问题,还有表格中的列吗?
  • 你有定义行顺序的列吗? (例如 sequence_number 或 score_id)
  • 我按日期列对行进行排序(不包括在内)。这是一个累积分数,因此日期和分数的顺序相同。

标签: sql database


【解决方案1】:

这是一种方法

with cte as
(SELECT
   ROW_NUMBER() OVER (PARTITION BY table.name ORDER BY id) row,
   name,
   score
 FROM table)
SELECT 
   a.name ,
   a.score - ISNULL(b.score,0)
FROM
   cte a
   LEFT  JOIN cte b
   on a.name = b.name
    and a.row = b.row+1

【讨论】:

  • 为什么说不需要 PARTITION BY?你不会假设所有的名字都是steve,是吗?
  • @Andriy M. 不确定我在想什么,a.row = b.row+1 绝对需要它。删除了注释。谢谢
  • 感谢您的帮助!第 3 行的行后需要有一个逗号,以供其他寻求此帮助的人使用。
  • @cwhelms 很高兴为您提供帮助。感谢您指出缺少的逗号。我修好了。
【解决方案2】:

另一种方法是使用 lag():

SELECT
   name,
   score - coalesce(lag(score) over (partition by name order by id), 0)
FROM table
ORDER BY name, id

TSQL 中的 lag() 函数 doesn't seem to be available 但在 cmets 中建议使用此解决方法:

select name,
    score - coalesce(
    MIN(score) OVER (PARTITION BY name ORDER BY id
             ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING)
    , 0) as diff
from table
order by name, id

【讨论】:

  • +1 但遗憾的是,AFAIK 这仅适用于 oracle。 OP 正在使用 SQL 2008(未标记,但在他的问题的第一行)
  • 我认为 Itzik Ben-Gan 指的是在 Oracle 中实现它的另一种方式。 OVER 子句不支持聚合的 ORDER BY 并且 SQL 没有类似 PRECEDING 的任何内容,请参阅此功能请求OVER clause enhancement request - ORDER BY for aggregates
  • 聚合没有排序?哎呀!没有这些我活不下去。 :-P 感谢您的澄清。
  • 顺便说一句,在 Postgres 中,如果您调用:lag(score, 1, 0),则不需要合并:1 和 0 表示一行,默认为 0。我想 Oracle 也是如此;我只是不确定。 ;-)
  • LAG() 在 SQL Server 2012 中可用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-21
  • 2017-03-13
  • 1970-01-01
相关资源
最近更新 更多