38

我有三个表,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

4 回答 4

15

I did a test on MS SQL 2005 using the following tables: A 400K rows, B 26K rows and C 450 rows.

The estimated query plan indicated that the basic inner join would be 3 times slower than the nested sub-queries, however when actually running the query, the basic inner join was twice as fast as the nested queries, The basic inner join took 297ms on very minimal server hardware.

What database are you using, and what times are you seeing? I'm thinking if you are seeing poor performance then it is probably an index problem.

于 2008-10-02T13:38:33.113 回答
11

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

But, if you're goal is just C's in each A, it might be easier to just use DISTINCT on the outer-most query.

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
于 2008-10-02T08:55:44.727 回答
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

I don't see a good reason why you want to limit the result sets of A and B because what you want to have is a list of all C's that are referenced by A. I did a distinct on C.valueC because i guessed you wanted a unique list of C's.


EDIT: I agree with your argument. Even if your solution looks a bit nested it seems to be the best and fastest way to use your knowledge of the data and reduce the result sets.

There is no distinct join construct you could use so just stay with what you already have :)

于 2008-10-02T08:55:56.880 回答
1

你是这个意思吗?

SELECT DISTINCT C.valueC
FROM 
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB
于 2008-10-02T08:54:05.560 回答