Сравнение данных в двух (или более) диапазонах в одном поле - PullRequest
0 голосов
/ 15 июля 2009

У меня есть простая таблица следующим образом

SQL> select * from test;

        ID STUFF
---------- ------------------------------------------------------------
         1 a
         2 b
         3 c
         4 d
         5 e
         6 f
         7 g

7 rows selected.

Я хотел бы построить запрос, который возвращает что-то вроде этого:

STUFF A    STUFF B
---------- --------------------------------------
a          e
b          f
c          g
d          NULL

То есть, взять два диапазона, определенных идентификатором, с отсутствующими значениями, дополненными NULL. Диапазоны непрерывны, могут перекрываться и имеют различную длину.

Возможно ли это? Если да, то что за запрос?


Temp таблица sql:

CREATE TABLE test(id number, stuff VARCHAR(20));
INSERT INTO test VALUES (1, 'a');
INSERT INTO test VALUES (2, 'b');
INSERT INTO test VALUES (3, 'c');
INSERT INTO test VALUES (4, 'd');
INSERT INTO test VALUES (5, 'e');
INSERT INTO test VALUES (6, 'f');
INSERT INTO test VALUES (7, 'g');

Ответы [ 3 ]

1 голос
/ 15 июля 2009
select a.stuff as stuffa, b.stuff as stuffb
from test as a
left join test as b
  on (a.id-:minida) = (b.id-:minidb)
  and b.id between :minidb and :maxidb
where a.id between :minida and :maxida

(где двоеточие обозначает идентификаторы для значений, которые связаны с подготовленным оператором) должно работать, если (maxidb-minidb) <= (maxida-minida). Но это не работает абсолютно симметрично (где один из диапазонов может быть больше другого).

Абсолютно симметричный запрос, который вы описываете, без сомнения может быть записан как чрезвычайно утомительный UNION, который в основном повторяет каждую часть (с соответствующей заменой) и добавляет вышеупомянутое выражение <= как условие в первый раз, то же самое, но с > вместо этого во второй раз (асимметрично, в случае, если диапазоны равны ;-), так что одна из двух половин объединения гарантированно будет пустой, но мне пришлось бы серьезно компенсировать скуку фактического выписывания сказал союз; -).

Если ваш любимый диалект SQL поддерживает FULL OUTER JOIN, то это может помочь ... но многие диалекты, такие как MySQL и SQLite, не поддерживают полную версию.

0 голосов
/ 15 июля 2009

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

@ тетра В основном любой допустимый диапазон для id. Длина и положение диапазонов неизвестны до развертывания.

@ Все Оптимальное решение является предпочтительным, и «это не может быть сделано аккуратно» является хорошим решением. Я могу сказать клиенту: «Это невозможно».

0 голосов
/ 15 июля 2009

Мне тяжело складывать голову вокруг того, что ты пытаешься сделать в целом. Но это утверждение будет работать на примере, который вы дали. Надеемся, что это указывает на правильное направление для более общего решения.

select stuff as stuffa,(select top 1 stuff from test where id >= t.id + 4 )stuffb from test t where t.Id<=4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...