найти пробелы в последовательности по группе - PullRequest
1 голос
/ 03 октября 2019

У меня есть таблица, где разные города и значения. Я хочу найти разрывы по городам, поэтому у меня есть таблица:

City    Value
Helsinki 1
Helsinki 2
Helsinki 5
Kuopio   4
Kuopio   5
Joensuu  1
Joensuu  2
Joensuu  3

И я хочу получить таблицу, где есть разрывы по городам, так что

 City     Value
 Helsinki 3
 Helsinki 4
 Kuopio   1
 Kuopio   2
 Kuopio   3
 Joensuu  4
 Joensuu  5

Я знаю, что могу использовать

select  rownum from dual connect by level<= 6 minus select value from table

но я не знаю, как я могу сделать это по группам.

Ответы [ 3 ]

2 голосов
/ 03 октября 2019

Вы можете использовать многораздельное внешнее объединение, которое будет более эффективным, чем само-объединение, и CROSS JOIN:

Oracle Setup :

CREATE TABLE table_name ( City, Value ) AS
SELECT 'Helsinki', 1 FROM DUAL UNION ALL
SELECT 'Helsinki', 2 FROM DUAL UNION ALL
SELECT 'Helsinki', 5 FROM DUAL UNION ALL
SELECT 'Kuopio',   4 FROM DUAL UNION ALL
SELECT 'Kuopio',   5 FROM DUAL UNION ALL
SELECT 'Joensuu',  1 FROM DUAL UNION ALL
SELECT 'Joensuu',  2 FROM DUAL UNION ALL
SELECT 'Joensuu',  3 FROM DUAL

Запрос :

SELECT city,
       v.value
FROM   ( SELECT LEVEL AS value
         FROM   DUAL
         CONNECT BY LEVEL <= ( SELECT MAX( value ) FROM table_name )
                             -- or just 5 if you want a static value
       ) v
       LEFT OUTER JOIN table_name t
       PARTITION BY ( t.City )
       ON ( v.value = t.value )
WHERE  t.value IS NULL

Выход :

CITY     | VALUE
:------- | ----:
Helsinki |     3
Helsinki |     4
Joensuu  |     4
Joensuu  |     5
Kuopio   |     1
Kuopio   |     2
Kuopio   |     3

дБ <> скрипка здесь

1 голос
/ 03 октября 2019

Этого можно добиться с помощью оператора МИНУС - ваша оригинальная идея

SQL> with city as (
  2  select 'Helsinki' as name, 1 as value from dual union all
  3  select 'Helsinki' as name, 2 as value from dual union all
  4  select 'Helsinki' as name, 5 as value from dual union all
  5  select 'Kuopio' as name, 4 as value from dual union all
  6  select 'Kuopio' as name, 5 as value from dual union all
  7  select 'Joensuu' as name, 1 as value from dual union all
  8  select 'Joensuu' as name, 2 as value from dual union all
  9  select 'Joensuu' as name, 3 as value from dual
 10  )
 11  SELECT NAME, LVL
 12  FROM (SELECT DISTINCT NAME FROM CITY)
 13  JOIN (SELECT LEVEL AS LVL FROM DUAL
 14          CONNECT BY LEVEL <= 5) ON ( 1 = 1 )
 15  MINUS
 16  SELECT NAME, VALUE
 17    FROM CITY
 18  ORDER BY 1, 2;

NAME            LVL
-------- ----------
Helsinki          3
Helsinki          4
Joensuu           4
Joensuu           5
Kuopio            1
Kuopio            2
Kuopio            3

7 rows selected.

SQL>

Cheers !!

1 голос
/ 03 октября 2019

Вы можете CROSS JOIN список различных городов с возможными значениями (от 1 до 5), а затем использовать LEFT JOIN антипаттерн для определения пропущенных значений:

SELECT c.city, v.value
FROM 
    (SELECT DISTINCT city FROM mytable) c
    CROSS JOIN (SELECT rownum value FROM DUAL CONNECT BY level<= 5) v
    LEFT JOIN mytable t ON t.city = c.city AND t.value = v.value
WHERE t.city IS NULL
ORDER BY c.city, v.value

Демонстрация на DB Fiddle :

CITY     | VALUE
:------- | ----:
Helsinki |     3
Helsinki |     4
Joensuu  |     4
Joensuu  |     5
Kuopio   |     1
Kuopio   |     2
Kuopio   |     3

Примечание: еще одна опция для генерации списка значений - вместо создания фиксированного списка чисел - начинать с доступных доступных значенийв таблице (это означает, что в таблице доступны все возможные значения):

CROSS JOIN (SELECT DISTINCT values FROM mytable) v
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...