Выберите строку, а затем несколько строк на основе значения в этой строке - PullRequest
0 голосов
/ 24 сентября 2018

У меня есть таблица myTable, и я хотел бы выбрать все строки, в которых B = DFW, а также все строки, в которых B = значение C, когда B = DFW.

Это то, что ядо сих пор, но по какой-то причине он возвращает только строки, где B = DFW:

SELECT * from myTable AS t1 WHERE EXISTS (
 SELECT C AS c_val from myTable WHERE t1.B="DFW" or (t1.B="DFW" and t1.C=c_val)
)

Он должен возвращать строку, где B = DFW и где B = DTW, как я уже сказал выше.

enter image description here

Ответы [ 2 ]

0 голосов
/ 24 сентября 2018

Мне нравится версия IN в ответе Шона.

Обычно можно переписать IN выражений в выражение, содержащее EXISTS.Я рассмотрю обе версии здесь и объясню различия.

Во-первых, некоторая преамбула, вот DDL для вашего набора данных:

drop table if exists myTable;

create table myTable (A text, B text, C text);
insert into myTable values ('WN', 'HOU', 'TUL');
insert into myTable values ('AA', 'MCO', 'ORD');
insert into myTable values ('AA', 'DFW', 'DTW');
insert into myTable values ('AA', 'ORD', 'DFW');
insert into myTable values ('F9', 'MCO', 'DTW');
insert into myTable values ('UA', 'LAS', 'LAX');
insert into myTable values ('WN', 'PHX', 'OAK');
insert into myTable values ('OO', 'DTW', 'ESC');
insert into myTable values ('AA', 'LGA', 'DCA');
insert into myTable values ('AA', 'LAX', 'DFW');

create index ix_myTable_001 on myTable (b);
create index ix_myTable_002 on myTable (c);

Вот версия запроса IN вместе с егоплан выполнения:

SELECT t.a, t.b, t.c
FROM mytable AS t
WHERE t.b = 'DFW' OR t.b IN (SELECT t2.c FROM mytable AS t2 WHERE t2.b = 'DFW');

explain query plan
SELECT t.a, t.b, t.c
FROM mytable AS t
WHERE t.b = 'DFW' OR t.b IN (SELECT t2.c FROM mytable AS t2 WHERE t2.b = 'DFW');

AA|DFW|DTW
OO|DTW|ESC

0|0|0|SEARCH TABLE mytable AS t USING INDEX ix_myTable_001 (b=?)
0|0|0|EXECUTE LIST SUBQUERY 1
1|0|0|SEARCH TABLE mytable AS t2 USING INDEX ix_myTable_001 (b=?)
0|0|0|SEARCH TABLE mytable AS t USING INDEX ix_myTable_001 (b=?)

Вот версия запроса EXISTS:

select * from myTable T1
where T1.b = 'DFW' OR exists (
SELECT 1
FROM myTable T2
WHERE T2.B = 'DFW'
AND T1.B = T2.C);

explain query plan
select * from myTable T1
where T1.b = 'DFW' OR exists (
SELECT 1
FROM myTable T2
WHERE T2.B = 'DFW'
AND T1.B = T2.C);

AA|DFW|DTW
OO|DTW|ESC

0|0|0|SCAN TABLE myTable AS T1
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 1
1|0|0|SEARCH TABLE myTable AS T2 USING INDEX ix_myTable_002 (c=?)

Обобщение: IN выражений заставляет подзапрос полностью вычисляться первым перед внешним запросомвыполняет.EXISTS выражения иногда и внешний запрос, и подзапрос могут оцениваться одновременно.Это означает большую гибкость при выполнении и, возможно, экономию при выполнении и использовании памяти.

Выбор версии IN по сравнению с версией EXISTS определяет, будет ли подзапрос генерировать маленький или большой результат.Если он маленький, выберите версию IN.Если он большой, то перейдите на версию EXISTS.

0 голосов
/ 24 сентября 2018

A UNION с CTE - это один из способов:

WITH dfws(a, b, c) AS (SELECT a, b, c FROM myTable WHERE b = 'DFW')
SELECT a, b, c FROM dfws
UNION
SELECT t.a, t.b, t.c
FROM myTable AS t
JOIN dfws AS d ON t.b = d.c;

Обычно вы используете CTE ( Общее табличное выражение ,вроде как представление, которое является локальным для одного запроса), чтобы определить dfws как все строки, где b - это «DFW».Затем вы возвращаете эти строки, а также результаты внутреннего объединения dfws с вашей исходной полной таблицей в строках, где b равно dfws.c.

Редактировать. Другой вариант - использоватьIN оператор:

SELECT t.a, t.b, t.c
FROM mytable AS t
WHERE t.b = 'DFW' OR t.b IN (SELECT t2.c FROM mytable AS t2 WHERE t2.b = 'DFW');

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

Для достижения наилучших результатов прилибо вам понадобится индекс для столбца b.

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