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

问题描述 投票:0回答:1

我的表格如下:

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'),

我想得到这样的报告:

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

换句话说,除了将连续的项目分组外,当它们的name的值不同时,这些组也被分为单独的组。 (换句话说,如果项目都是连续的并且具有相同的精确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是它们之间的数字差,当然是不对的。

我感觉很像this question might be related,但是我并没有太大的意义,当我尝试将其调整到表中时,它或多或少地相当于一个简单的SELECT *。我需要对查询进行哪些修改才能使其正常工作?

mysql sql mariadb gaps-and-islands
1个回答
0
投票

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

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

我之所以这样说,是因为如果没有窗口功能,差距和岛屿将更具挑战性。这就引出了一个问题,即为什么不使用更新版本的MariaDB。无论如何,10.1的寿命终止于今年10月。

© www.soinside.com 2019 - 2024. All rights reserved.