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