这是一个差距和孤岛问题,这是解决它的另一种方法,它也使用变量:
SELECT
MIN(a) AS series_start,
MAX(a) AS series_end,
MAX(a) - MIN(a) + 1 AS series_count
FROM (
SELECT
a,
@r := @r + 1 AS r
FROM
yourtable,
(SELECT @r := 0) AS x
ORDER BY
a
) s
GROUP BY
a - r
ORDER BY
a - r
;
这就是它的工作原理。
子查询将行号分配给表行并返回此行集:
a r
-- --
1 1
2 2
3 3
5 4
6 5
7 6
9 7
10 8
11 9
12 10
在这种情况下r
,存储行号的列恰好与id
数据样本中的列匹配,但我假设通常该id
列可能有间隙,因此不能在此处使用。
r
主查询按和之间的差异对结果进行分组a
:对于顺序值,它总是相同的:
a r a - r
-- -- -----
1 1 0
2 2 0
3 3 0
5 4 1
6 5 1
7 6 1
9 7 2
10 8 2
11 9 2
12 10 2
这允许我们将这些行组合在一起。此时剩下的就是获取最小值、最大值和计数,这将为您提供以下输出:
series_start series_end series_count
------------ ---------- ------------
1 3 3
5 7 3
9 12 4
这个查询的 SQL Fiddle 演示,我借用了@sgeddes 的模式,可以在这里找到。
更新
由于不能使用数字变量(根据评论),您可以使用三角形自连接来分配行号,但它的效率会比使用变量低得多。无论如何,这是修改后的版本,对先前查询的更改以粗体突出显示:
选择
MIN(a) AS series_start,
MAX(a) AS series_end,
MAX(a) - MIN(a) + 1 AS series_count
从 (
选择
数据.a,
计数(*)作为 r
从
yourtable AS 数据
内部联接
yourtable AS 计数
上
data.id >= tally.id
通过...分组
数据.a
) 年代
通过...分组
a - r
订购方式
a - r
;
该方法本身保持不变:子查询返回一个排序的行集,然后像以前一样对其进行处理。
此处提供了修改后查询的 SQL Fiddle 演示。