2

我刚开始学习 MySQL,我遇到了这个问题,我非常需要解决方案或只是逻辑。

例如我有这张表:

id         a 
--        --
 1         1
 2         2
 3         3
 4         5
 5         6
 6         7
 7         9
 8        10
 9        11
10        12

现在,我想要的是显示列a中应该按系列分组的所有数据。在这种情况下,结果应该是:

series_start|series_end|count
------------+----------+-----
           1          3     3
           5          7     3
           9         12     4

这需要很多子查询和连接。我现在无法弄清楚。

4

2 回答 2

2

这是一个问题,这是解决它的另一种方法,它也使用变量:

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 演示。

于 2013-10-11T13:32:48.217 回答
0

这是使用的一种解决方案user defined variables

select min(series_start) series_start, 
  max(series_end) series_end,
  1 + max(series_end) - min(series_start) count
from (
  select t1.a series_start, 
    t2.a series_end,
    @val:=IF(@prev=t2.a-1,@val,@val+1) val,
    @prev:=t2.a
  from yourtable t1
    join yourtable t2 on t1.a = t2.a-1
    join (select @val:= 0, @prev:= 0) t
  order by t2.a
  ) t
group by val
于 2013-10-10T01:37:28.287 回答