在SQL中使用DISTINCT内部联接

时间:2008-10-02 08:48:45

标签: sql distinct inner-join

我有三个表,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慢一倍。

4 个答案:

答案 0 :(得分:14)

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

估计的查询计划表明基本的内部联接比嵌套的子查询慢3倍,但是当实际运行查询时,基本内部联接的速度是嵌套查询的两倍,基本的内部联接采取了非常小的服务器硬件上297毫秒。

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

答案 1 :(得分:9)

我相信您的 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

答案 2 :(得分: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列表。


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

您可以使用没有明显的连接构造,所以只需保留已有的东西:)

答案 3 :(得分:0)

这是你的意思吗?

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