Подтвердить что ты не робот

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

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

Мои таблицы выглядят примерно так: A [id, valueA, lookupB], B [id, valueB, lookupC], C [id, valueC]. Я написал запрос с двумя вложенными 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

EDIT: Таблицы довольно большие, 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, которые я делаю выше.

4b9b3361

Ответ 1

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

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

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

Ответ 2

Я считаю, что ваши отношения 1: m должны уже неявно создавать DISTINCT JOINs.

Но, если вы цель, это всего лишь 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

Ответ 3

Это то, что вы имеете в виду?

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

Ответ 4

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.


EDIT. Я согласен с вашим аргументом. Даже если ваше решение выглядит немного вложенным, это, по-видимому, самый лучший и быстрый способ использовать ваши знания данных и уменьшить наборы результатов.

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