我有一个名为myTable的表,我想选择B = DFW的所有行,以及B = DFW时选择B = C值的所有行。
这是我到目前为止的内容,但是由于某种原因,它只返回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的行。
答案 0 :(得分:2)
使用CTE的UNION是一种方法:
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 (Common Table Expression,类似于单个查询本地的视图)将dfws
定义为{{1 }}是“ DFW”。然后,您返回这些行,以及b
与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列上都有一个索引。
答案 1 :(得分:0)
我喜欢肖恩答案中的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
版本。