SQL-запрос для возврата строк, отсортированных по ключу плюс пустые строки для отсутствующих ключей - PullRequest
3 голосов
/ 22 ноября 2008

У меня есть таблица, которая, по сути, имеет такую ​​структуру:

 key        value
 ------     ------
 2          val1
 3          val2
 5          val3

Ключи представляют собой последовательные целые числа от 1 до (в настоящее время) 1 миллиона, увеличивающиеся на несколько тысяч каждый день. Пробелы в ключах возникают при удалении записей.

Я ищу SQL-запрос, который возвращает это:

 key        value
 ------     ------
 1
 2          val1
 3          val2
 4 
 5          val3

Я вижу, как это сделать, присоединившись ко второй таблице с полным списком ключей. Однако я бы предпочел решение, которое использует стандартный SQL (без хранимых процедур или второй таблицы ключей), и оно будет работать независимо от того, какое верхнее значение ключа.

Ответы [ 4 ]

3 голосов
/ 22 ноября 2008

SQL-запросы не имеют механизма зацикливания. Языки процедур имеют циклы, но сами запросы могут «зацикливать» только те данные, которые они находят в таблице (или производной таблице).

Что мне нужно сделать, чтобы создать список чисел на лету, так это сделать перекрестное соединение на небольшой таблице цифр от 0 до 9:

CREATE TABLE n (d NUMERIC);
INSERT INTO n VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);

Затем сгенерировать 00..99:

SELECT n1.d + n2.d*10 AS d
FROM n AS n1 CROSS JOIN n AS n10;

Если вы хотите только 00..57:

SELECT n1.d + n2.d*10 AS d
FROM n AS n1 CROSS JOIN n AS n2
WHERE n1.d + n2.d*10 <= 57;

Конечно, вы можете присоединиться к таблице для места 100, места 1000 и т. Д. Обратите внимание, что вы не можете использовать псевдонимы столбцов в предложении WHERE, поэтому вам придется повторить полное выражение.

Теперь вы можете использовать это как производную таблицу в предложении FROM и присоединить ее к вашей таблице данных.

SELECT n0.d, mytable.value
FROM
   (SELECT n1.d + n2.d*10 + n2.d*100 + n3.d*1000 
      + n4.d*10000 + n5.d*100000 AS d
    FROM n AS n1 CROSS JOIN n AS n2 CROSS JOIN n AS n3 
      CROSS JOIN n AS n4 CROSS JOIN n AS n5) AS n0
  LEFT OUTER JOIN mytable ON (n0.d = mytable.key)
WHERE n0.d <= (SELECT MAX(key) FROM mytable);

Вам нужно добавить еще CROSS JOIN каждый раз, когда размер вашей таблицы превышает порядок. Например. когда он превысит 1 миллион, добавьте объединение для n6.

Обратите внимание, что теперь мы можем использовать псевдоним столбца в предложении WHERE внешнего запроса.

По общему признанию, это может быть довольно дорогим запросом сделать это исключительно в SQL. Вы можете обнаружить, что проще и быстрее «заполнить пробелы», написав некоторый код приложения.

1 голос
/ 23 ноября 2008

Другой метод - создать набор результатов из миллиона чисел и использовать его в качестве основы для объединения. Это может сделать работу за вас. (украдено у ASKTOMs Блог )

select  level
from    dual
connect by level <= 1000000

получая что-то вроде этого

WITH 
upper_limit AS
(
    select 1000000 limit from dual
),
fake_table AS
(
    select  level key
    from    dual
    connect by level <= (select limit from upper_limit)
)
select key, value
from table, fake_table
where fake_table.key = table.key(+)

Я не на работе, поэтому я не могу это проверить. Ваш пробег может варьироваться. Я использую Oracle на работе.

0 голосов
/ 22 ноября 2008
WITH range (num) AS (
SELECT 1 -- use your own lowerbound
UNION ALL
SELECT 1 + num FROM range
WHERE num < 10 -- use your own upper bound
)
SELECT r.num, y.* FROM range r left join yourtable y
on r.num = y.id
0 голосов
/ 22 ноября 2008

В MySQL вы можете найти края пропусков, выполняя левое соединение против себя с положительным и отрицательным смещением.

Например:

create table seq ( i int primary key, v varchar(10) );

insert into seq values( 2, 'val1' ), (3, 'val2' ), (5, 'val3' );


select s.i-1 from seq s left join seq m on m.i = (s.i -1) where m.i is null;

+-------+
| s.i-1 |
+-------+
|     1 |
|     4 |
+-------+


select s.i+1 from seq s left join seq m on m.i = (s.i +1) where m.i is null;
+-------+
| s.i+1 |
+-------+
|     4 |
|     6 |
+-------+

Это не дает вам того, чего вы хотите, но дает достаточно информации, чтобы понять, что такое пропущенные строки.

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