Использование внутреннего соединения DISTINCT в SQL

StackOverflow https://stackoverflow.com/questions/161404

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть три таблицы: A, B, C, где A — это многие к одному B, а B — многие к одному C.Мне нужен список всех C в A.

Мои таблицы примерно такие:A[id, значениеA, поискB], B[id, значениеB, поискC], C[id, значениеC].Я написал запрос с двумя вложенными SELECT, но мне интересно, можно ли как-нибудь выполнить INNER JOIN с DISTINCT.

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 — 500 тысяч строк, B — 10 тысяч строк и 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, который я сделал выше).

Это было полезно?

Решение

Я провел тест на MS SQL 2005, используя следующие таблицы:A 400 тысяч строк, B 26 тысяч строк и C 450 строк.

Предполагаемый план запроса показал, что базовое внутреннее соединение будет в 3 раза медленнее, чем вложенные подзапросы, однако при фактическом выполнении запроса базовое внутреннее соединение было в два раза быстрее, чем вложенные запросы. минимальное серверное оборудование.

Какую базу данных вы используете и какое время вы видите?Я думаю, если вы видите плохую производительность, то, вероятно, это проблема с индексом.

Другие советы

Я верю твоему 1:м отношения уже должны неявно создавать DISTINCT JOIN.

Но если ваша цель — это только C в каждом A, возможно, будет проще использовать 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
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, потому что вам нужен список всех C, на которые ссылается A.Я сделал особый акцент на C.valueC, потому что догадался, что вам нужен уникальный список C.


РЕДАКТИРОВАТЬ:Я согласен с вашим аргументом.Даже если ваше решение выглядит несколько вложенным, оно кажется лучшим и самым быстрым способом использовать ваши знания о данных и сократить наборы результатов.

Не существует отдельной конструкции соединения, которую вы могли бы использовать, поэтому просто оставайтесь с тем, что у вас уже есть :)

Ты это имеешь ввиду?

SELECT DISTINCT C.valueC
FROM 
C
INNER JOIN B ON C.id = B.lookupC
INNER JOIN A ON B.id = A.lookupB
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top