【问题标题】:Using DISTINCT inner join in SQL在 SQL 中使用 DISTINCT 内连接
【发布时间】:2010-09-14 18:06:08
【问题描述】:

我有三个表,A、B、C,其中 A 是多对一 B,B 是多对一 C。我想要 A 中所有 C 的列表。

我的表是这样的:A[id, valueA, lookupB], B[id, valueB, lookupC], C[id, valueC]。我用两个嵌套的 SELECT 编写了一个查询,但我想知道是否有可能以某种方式使用 DISTINCT 进行 INNER JOIN。

SELECT valueC
FROM C
INNER JOIN
(
    SELECT DISTINCT lookupC
    FROM B INNER JOIN
    (
        SELECT DISTINCT lookupB
        FROM A
    ) 
    A2 ON B.id = A2.lookupB
) 
B2 ON C.id = B2.lookupC

编辑: 这些表相当大,A 是 500k 行,B 是 10k 行,C 是 100 行,所以如果我做一个基本的内部连接并最后使用 DISTINCT,就会有很多不必要的信息,如下所示:

SELECT DISTINCT valueC
FROM 
C INNER JOIN B on C.id = B.lookupB
INNER JOIN A on B.id = A.lookupB

这非常非常慢(比我上面做的嵌套 SELECT 慢几倍。

【问题讨论】:

    标签: sql distinct inner-join


    【解决方案1】:

    我使用下表对 MS SQL 2005 进行了测试:A 400K 行、B 26K 行和 C 450 行。

    估计的查询计划表明基本内连接会比嵌套子查询慢 3 倍,但是在实际运行查询时,基本内连接是嵌套查询的两倍,基本内连接需要在极少的服务器硬件上为 297 毫秒。

    您使用的是什么数据库,您查看的时间是什么?我在想,如果您看到性能不佳,那可能是索引问题。

    【讨论】:

    • 这是一个索引问题。我使用的是 MSSQL 2005,终于找到了 Database Engine Tuning Advisor。我在 A.lookupB 上添加了一个索引,它大大加快了速度。感谢您的帮助!
    【解决方案2】:

    我相信您的 1:m 关系应该已经隐式地创建了 DISTINCT JOIN。

    但是,如果您的目标只是每个 A 中的 C,那么在最外层的查询上使用 DISTINCT 可能会更容易。

    SELECT DISTINCT a.valueA, c.valueC
    FROM C
        INNER JOIN B ON B.lookupC = C.id
        INNER JOIN A ON A.lookupB = B.id
    ORDER BY a.valueA, c.valueC
    

    【讨论】:

    • 事实证明已经足够了,我遇到的问题是我没有索引。
    【解决方案3】:
    SELECT DISTINCT C.valueC 
    FROM C 
      LEFT JOIN B ON C.id = B.lookupC
      LEFT JOIN A ON B.id = A.lookupB
    WHERE C.id IS NOT NULL
    

    我看不出你想要限制 A 和 B 的结果集的充分理由,因为你想要的是 A 引用的所有 C 的列表。我在 C.valueC 上做了一个不同的,因为我猜你想要一个独特的 C 列表。


    编辑:我同意你的论点。即使您的解决方案看起来有点嵌套,它似乎也是使用您的数据知识并减少结果集的最佳和最快的方法。

    没有可以使用的独特连接结构,所以只需保留已有的内容即可:)

    【讨论】:

    • 结果是一样的,但是好像慢了点。我不知道确切原因,但我猜这是因为它创建了两个巨大的连接表 C.valueC 会非常大。因为我知道 B.lookupC 本身应该是 DISTINCT,所以我想利用这些知识来加快速度。
    【解决方案4】:

    这是你的意思吗?

    SELECT DISTINCT C.valueC
    FROM 
    C
    INNER JOIN B ON C.id = B.lookupC
    INNER JOIN A ON B.id = A.lookupB
    

    【讨论】:

    • 不幸的是,这似乎很慢,因为它需要先创建巨大的连接表。当我运行我的代码时它会更快,我猜这是因为它修剪了连接表。
    • 我已经颠倒了连接顺序,这取决于您使用的 SQL,可能会提高查询的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多