【问题标题】:SQL Count Grouping by a sequence of numbersSQL Count 按数字序列分组
【发布时间】:2013-02-07 15:43:52
【问题描述】:

我有一个这样的 SQL 表:

id      pNum
-----   --------
100     12
100     13
100     15
100     16
100     17
200     18
200     19
300     20
300     21
300     25

我想按 id 和 pNum 序列分组,并计算行数。有这样的结果。

id      res
-----   --------
100     2
100     3
200     2
300     2
300     1

有什么想法吗?

【问题讨论】:

  • 你用的是什么 rdbms?
  • res 在分组表中代表什么
  • 微软 SQL ------
  • 哦,您将“res”分组为连续序列,对吧?
  • res 是按 pnum 序列分组的 id 计数

标签: sql sql-server group-by sequence gaps-and-islands


【解决方案1】:

如果您的 DBMS 支持窗口函数(例如 SQL Server 2005+)

SELECT id,
       count(*) AS res
FROM   (SELECT *,
               [pNum] - ROW_NUMBER() OVER (PARTITION BY [id] ORDER BY [pNum]) AS Grp
        FROM   YourTable) T
GROUP  BY id,
          Grp 

SQL Fiddle

【讨论】:

  • @user2051336 - 这种类型的需求通常被称为寻找“差距和孤岛”。我的回答中的方法归功于 Itzik Ben Gan AFAIK。您使用的是哪个版本的 SQL Server?
  • @MartinSmith - 这个也可能对 MS SQL 服务器有用stackoverflow.com/a/4324654/247184
【解决方案2】:

使用this question的解决方案:

declare @table table
(
    id int
    , pnum int
)


insert into @table
values (100,    12)
, (100,     13)
, (100,     15)
, (100,     16)
, (100,     17)
, (200,     18)
, (200,     19)
, (300,     20)
, (300,     21)
, (300,     25)

;WITH numbered AS (
  SELECT
    ID, pnum,
    SeqGroup = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY pnum) - pnum
  FROM @table
)
SELECT
  ID,
  COUNT(*) AS res
FROM numbered
GROUP BY ID, SeqGroup
ORDER BY id, MIN(pnum)

【讨论】:

  • row_number() - pnum 的绝妙技巧。这个赋值的东西SeqGroup = 是做什么的?
  • @a_horse_with_no_name - 我怀疑您可能知道这是 SQL Server 特定的列别名方式。
  • @MartinSmith:不是真的。 as foo 标准语法有区别吗?
  • @a_horse_with_no_name - 不是真的。有些人(例如 Aaron Bertrand)更喜欢它,因为它更容易填充列别名。 Bad Habits to Kick : Using AS instead of = for column aliases
猜你喜欢
  • 1970-01-01
  • 2021-05-05
  • 1970-01-01
  • 2015-10-17
  • 1970-01-01
  • 2014-08-01
  • 2011-07-04
  • 2018-05-13
  • 1970-01-01
相关资源
最近更新 更多