Найти пропущенные значения в буквенно-цифровой последовательности - PullRequest
0 голосов
/ 14 ноября 2018

Я хочу определить пропущенные значения в буквенно-цифровой последовательности.

Таблица определена следующим образом:

CREATE TABLE `seqtest` (
  `ID` int(11) NOT NULL,
  `PoleNo` text,
  `Pre` char(1) DEFAULT NULL,
  `Num` int(3) DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Данные приведены ниже и всегда будут состоять из одной буквы (AZ), за которой следуют три цифры от 000 до 999.

| PoleNo |  Pre  |  Num  |
|------------------------|
| A000   |   A   |  000  |
| A001   |   A   |  001  |
| A002   |   A   |  002  |
| A004   |   A   |  003  |
| ****   |   *   |  ***  |
| A998   |   A   |  998  |
| A999   |   A   |  999  |
| B000   |   B   |  000  |
| B001   |   B   |  001  |
| B002   |   B   |  002  |
| ****   |   *   |  ***  |
| B998   |   B   |  998  |
| B999   |   B   |  999  |
| C000   |   C   |  000  |
| C001   |   C   |  001  |
| C005   |   C   |  005  |
| C006   |   C   |  006  |
|------------------------|

Я хочу, чтобы запрос обнаружил, что, например, C002, C003 и C004 отсутствуют, как показано ниже.

|  Pre  | start | stop |
|   C   |   2   |   4  |
|----------------------|

Я использую следующее:

SELECT l.Pre, l.Num + 1 as start, min(fr.Num) - 1 as stop
FROM seqtest as l
    LEFT OUTER JOIN seqtest as r ON l.Num = r.Num - 1 AND l.Pre = r.Pre
    LEFT OUTER JOIN seqtest as fr ON l.Num < fr.Num AND l.Pre = fr.Pre
WHERE r.Num is null AND l.Num < 999
GROUP BY l.Pre, l.Num, r.Num

, основанное на this .

Это дает мне диапазон, который отсутствует и работает хорошо, за исключением одного случая ... когда «Pre» меняется с одной буквы на другую.

IE Со следующими данными:

| PoleNo |  Pre  |  Num  |
|------------------------|
| B995   |   B   |  995  |
| B996   |   B   |  996  |
| B997   |   B   |  997  |
| C003   |   C   |  003  |
| C004   |   C   |  004  |
| C005   |   C   |  005  |
| C006   |   C   |  006  |
|------------------------| 

Я хотел бы иметь возможность вернуть это:

|  Pre  | start | stop |
|   B   |  998  |  999 |
|   C   |   0   |   2  |
|----------------------|

Возможно ли это?Я использую поля Pre и Num, которые просто разбиты на поля PoleNo ... но если кто-нибудь найдет способ сделать это, просто используя поле PoleNo, это также сработает.

1 Ответ

0 голосов
/ 14 ноября 2018

Это намного проще в MySQL 8+, потому что у вас есть lead().Но вы можете делать то, что вы хотите:

select st.pre,
       (st.num + 1) as start,
       (st.next_num - 1) as stop
from (select st.*,
             (select st2.num
              from seqtest st2
              where st2.pre = st.pre and
                    st2.num > st.num
              order by st2.num asc
              limit 1
             ) as next_num
      from seqtest st
     ) st
where next_num <> num + 1;

РЕДАКТИРОВАТЬ:

Это также получает диапазоны в начале и в конце:

select st.pre, 
       (st.num + 1) as start,
       (st.next_num - 1) as stop
from (select st.pre, num,
             coalesce( (select st2.num
                        from seqtest st2
                        where st2.pre = st.pre and
                              st2.num > st.num
                        order by st2.num asc
                        limit 1), 1000
                      ) as next_num
      from seqtest st
      union
      select st.pre, 0 as num, min(st.num) as next_num
      from seqtest st
      group by st.pre
     ) st
where next_num <> num + 1
order by pre, start;

Здесь - это дБ <> скрипка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...