过滤掉sql中不满足条件的行的最快方法是什么?

问题描述 投票:0回答:2

假设我有一张有结构的表格

(
  id int,
  value int,
  key int
)

我只想留下那些与

id
相对应的行,其中至少有一次具有某些
key
。例如,如果需要
key
等于
5
,则从表

id value key
1  1     1
1  1     2
2  1     5
2  3     2
3  5     4
3  5     5

我想要得到结果

id value key
2  1     5
2  3     2
3  5     4
3  5     5

因为

id
1 的对象在
key
列中没有 5,而其他对象则有。 我知道有两种方法可以做到这一点,在这两种方法中,我们都创建一个带有所需 id 的
tmp_table
,例如

select [distinct] id from example_table where key=5

然后进行过滤:

select * from example_table where id in tmp_table

或加入:

select e.* from example_table e join tmp_table t on e.id = t.id

对于这些场景我有几个问题:

  1. 这两种方式的性能有区别吗?一般情况下以及在 Vertica 中。
  2. 对于连接方法我必须使用
    distinct
    ,否则数据将重复。我必须采用第一种方法吗?从一方面来说
    distinct
    是昂贵的操作,从另一方面来说
    in
    应该更快(如果没有某种哈希表)
  3. 还有第三种方法可以达到预期的效果吗?
sql vertica
2个回答
0
投票
  1. Vertica 执行优化,
    IN
    JOIN
    方法都可能执行类似的操作。
  2. 如果多行可以共享同一个id,则连接方法需要
    DISTINCT
  3. 另一种方法是使用
    EXISTS
    来避免
    DISTINCT
    SELECT e.* FROM example_table e
    WHERE EXISTS (
      SELECT 1 FROM example_table WHERE id = e.id AND key = 5
    );

您还可以使用Vertica的

EXPLAIN
命令来检查不同方法的执行情况。


0
投票

另外两种方式:

  1. 内部联接,完全选择
    id
    为 5 的所有
    value
    行:
WITH
id_s AS (
  SELECT
    id
  FROM indata
  WHERE key = 5
)
SELECT
  i.*
FROM indata i
INNER JOIN id_s USING(id)
;
  1. WHERE IN(<fullselect>)
    谓词:

SELECT
  *
FROM indata
WHERE id IN (
  SELECT id FROM indata
  WHERE key=5
);
© www.soinside.com 2019 - 2024. All rights reserved.