【问题标题】:Best way to eliminate duplicates rows after multiple joins多次连接后消除重复行的最佳方法
【发布时间】:2021-09-06 07:08:57
【问题描述】:

我会考虑三个简单的表格。 A、B 是我的实体表,C 是在 A 和 B 之间创建多对多关系的中间表。

架构:

A: (id INTEGER PRIMARY KEY)
B: (id INTEGER PRIMARY KEY)
C: (
  A_id INTEGER, 
  B_id INTEGER, 
  FOREIGN KEY(A_id) REFERENCES A(id), 
  FOREIGN KEY(B_id) REFERENCES B(id)
)

现在,考虑下面的查询

SELECT
  A.id
FROM A
LEFT OUTER JOIN C
  ON (A.id = C.A_id)
LEFT OUTER JOIN B
  ON (C.B_id = B.id)
WHERE ...;

此查询将导致 A.id 的重复值,这是预期的,因为 C 可能有多行与 A 的每一行关联。我的问题是消除这些重复并获取 A 记录的最佳方法是什么。我只需要 A 记录。

我知道两种方法,

-- Using DISTINCT
SELECT
  DISTINCT(A.id), ...
FROM A
LEFT OUTER JOIN C
  ON (A.id = C.A_id)
LEFT OUTER JOIN B
  ON (C.B_id = B.id)
WHERE ...
  ORDER BY A.id;

-- Or using A.id IN (above query)/ A.id = Any(above query)
SELECT 
  ...
FROM A 
WHERE A.id IN (
  SELECT
    A.id
  FROM A
  LEFT OUTER JOIN C
    ON (A.id = C.A_id)
  LEFT OUTER JOIN B
    ON (C.B_id = B.id)
  WHERE ...
);

我正在使用 PostgreSQL。我需要包含所有用于过滤的表,因此不能将不加入表视为一种改进。我已经分析了这两个查询,但我仍然觉得可能有更好的方法来做到这一点(就性能而言)。

非常感谢任何帮助!

【问题讨论】:

  • 这在很大程度上取决于条件。为什么要使用 left joinwhere 子句?
  • 因为我需要 WHERE 子句中 B & A 的属性

标签: sql postgresql query-optimization


【解决方案1】:

您也可以尝试以下查询:

SELECT
    a.* -- or whatever columns you need of a
FROM a
WHERE EXISTS(
    SELECT 1
    FROM c
    WHERE c.a_id = a.id
)

请注意,不需要连接表b,因为c 中的行的存在始终保证b 中的行,并且您不需要此行/表中包含的任何信息。

也许更干净的可能是:

SELECT DISTINCT
    a.* -- or whatever columns you need of a
FROM a
LEFT JOIN c

您可以使用EXPLAIN ANALYZE <query> 查看查询计划和执行时间。也许这会提示您最好使用什么。 但请注意缓存,以这种方式多次重复这两个查询以查看可比较的结果。

【讨论】:

  • 其实这只是一个例子,真正的查询是连接4个表,我需要WHERE子句中所有4个表的数据,所以第二种方法不可行。
  • 请编辑问题以反映您的真实需求,以便您获得可行的答案。 @Crash0v3rrid3
【解决方案2】:

我建议exists:

SELECT A.id
FROM A
WHERE EXISTS (SELECT 1
              FROM C JOIN
                   B
                   ON C.B_id = B.id
              WHERE A.id = C.A_id AND . . . 
             )

【讨论】:

  • 我会在实际的桌子上试一试。谢谢!
猜你喜欢
  • 1970-01-01
  • 2020-09-30
  • 2016-01-16
  • 2014-12-31
  • 1970-01-01
  • 1970-01-01
  • 2014-01-24
  • 1970-01-01
  • 2020-09-12
相关资源
最近更新 更多