提问者:小点点

2列上的间隙和岛-如果A列连续而B列相同


我有一张表格如下:

CREATE TABLE `table` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
    `cc` int(3) unsigned NOT NULL,
    `number` int(10) NOT NULL,
    `name` varchar(64) NOT NULL,
    `datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB

DBMS是Debian 9.1上的MariaDB 10.1.26。 我一直试图让它列出连续数字的范围。 通过下面的查询,我能够实现这一点:

SELECT min(number) first_number, max(number) last_number, count(*) AS no_records FROM (
    SELECT c.*, @rn := @rn + 1 rn
    from (SELECT number FROM table WHERE cc = 1 GROUP BY number ORDER BY number) AS c
    CROSS JOIN (SELECT @rn := 0) r
) c
GROUP BY number - rn ORDER BY number ASC

但是,如果我希望根据附加列中的值将项聚在一起,这就不起作用了。 假设我希望只有当项目的name值都相同时才对它们分组。 说这是我的数据:

INSERT INTO `table` (`id`, `cc`, `number`, `name`) VALUES
(1, 1, 12, 'Hello'),
(2, 1, 2, 'Apple'),
(3, 1, 3, 'Bean'),
(4, 1, 10, 'Hello'),
(5, 1, 11, 'Hello'),
(6, 1, 1, 'Apple'),
(7, 1, 14, 'Deer'),
(8, 1, 14, 'Door'),
(9, 1, 15, 'Hello'),
(10, 1, 17, 'Hello'),

我想要一份这样的报告:

first  last   count  name
1      2      2      Apple
3      3      1      Bean
10     12     3      Hello
14     14     1      Deer
14     14     1      Door
15     15     1      Hello
17     17     1      Hello

换句话说,除了对连续的项进行分组外,当这些组的name值不同时,它们还被拆分成单独的组。 (换句话说,只有当所有项都是连续的并且具有相同的名称时,它们才会一起在一个岛中)。 我来过的最接近(也不是很接近)的方法是:

SELECT min(number) first_number, max(number) last_number, count(*) AS no_records FROM (
    SELECT c.*, @rn := @rn + 1 rn
    from (SELECT number FROM table WHERE cc = 1 GROUP BY number, name ORDER BY number) AS c
    CROSS JOIN (SELECT @rn := 0) r
) c
GROUP BY number - rn, name ORDER BY number ASC

但是,这是行不通的,它似乎将名称的第一个外观返回为first,最后一个外观返回为last,其中no_records是它们之间的数字差值,这肯定是完全不对的。

我觉得这个问题可能是相关的,但我并不能理解它的意义,当我尝试将它调整到我的表中时,它或多或少只是做了一个简单的select*。 我需要对我的查询进行哪些修改才能使其工作?


共1个答案

匿名用户

你的例子不是一个空隙和孤岛的问题。 如果它代表您的实际问题,您可以只使用聚合:

select min(number), max(number), count(*), name
from t
group by name;

我这样说是因为如果没有窗口函数,缺口和岛就更具有挑战性。 这就引出了为什么不使用MariaDB的最新版本的问题。 无论如何,10.1的寿终正寝是今年10月。

相关问题