Как избежать неоднозначного использования полного внешнего соединения? - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть три таблицы, которые необходимо объединить.

Несколько столбцов, таких как "P_SERIAL_ID", "CONTACT_NOTE" ... и т. Д., Будут неоднозначными, если я использую запрос ниже.

"P_SERIAL_ID "и" CONTACT_NOTE "являются столбцами, принадлежащими" B_COLLECTION "." COLLECTION_CONSENT_RC "и" B_TRACE "." P_TC_RC ".«B_TRACE». «P_TC_DATA» не имеет этих двух столбцов.

Как решить эту проблему?

SELECT "P_SERIAL_ID","CONTACT_NOTE" 
FROM (
  SELECT * 
  FROM "B_TRACE"."P_TC_DATA" AS DAT
    FULL OUTER JOIN "B_COLLECTION"."COLLECTION_CONSENT_RC" AS SUBID ON DAT."P_SERIAL_ID" = SUBID."SUBJECT_ID"
    FULL OUTER JOIN "B_TRACE"."P_TC_RC" AS TR ON TR."P_SERIAL_ID" = DAT."P_SERIAL_ID"
  WHERE DAT."STATE_ID" IN ('7','8','9')
) AS SHIT0 
WHERE "SUBJECT_CITIZEN_ID" IS NOT NULL;

Я хочу, чтобы этот запрос достиг этого без неоднозначности.shit0 выполняет условие и содержит все три таблицы без неоднозначности.enter image description here

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

Во-первых, FULL JOIN редко требуется и не подходит в этой ситуации.

SELECT DAT."P_SERIAL_ID", ?."CONTACT_NOTE"    -- Add the table alias!
FROM "B_TRACE"."P_TC_DATA" DAT LEFT JOIN
     "B_COLLECTION"."COLLECTION_CONSENT_RC" SUBID
     ON DAT."P_SERIAL_ID" = SUBID."SUBJECT_ID" LEFT JOIN
     "B_TRACE"."P_TC_RC" TR
     ON TR."P_SERIAL_ID" = DAT."P_SERIAL_ID"
WHERE DAT."STATE_ID" IN ('7', '8', '9') AND  -- Are these really strings?
      ?."SUBJECT_CITIZEN_ID" IS NOT NULL;    -- Add the table alias!

Примечания:

  • Никаких подзапросов не требуется.
  • Предложение WHERE превращает FULL JOIN в LEFT JOIN в любом случае.FULL JOIN почти никогда не требуется в четко определенной модели данных.
  • Список IN - это строки в вашем примере.Вероятно, это числа, поэтому вы должны бросить одинарные кавычки.
  • Указать ALL имена таблиц.Приведенный выше запрос содержит ? в качестве заполнителя для псевдонима таблицы.
  • Избавьтесь от двойных кавычек в вашем запросе.Они только усложняют написание и чтение.
  • В зависимости от таблицы, откуда взято SUBJECT_CITIZEN_ID, все JOIN могут действительно быть INNER JOIN с.
0 голосов
/ 28 ноября 2018

Полностью квалифицируйте все свои столбцы, даже подумайте о переименовании, чтобы они были уникальными:

SELECT dat_serial_id, tr_serial_id, dat_contact_note, tr_contact_note
FROM (
  SELECT 

    "DAT"."P_SERIAL_ID" as dat_serial_id,
    "TR"."P_SERIAL_ID" as tr_serial_id,
    "DAT"."CONTACT_NOTE" as dat_contact_note,
    "TR"."CONTACT_NOTE" as tr_contact_note,
    "SUBID"."SUBJECT_CITIZEN_ID" --guessed at the table


  FROM "B_TRACE"."P_TC_DATA" AS DAT
    FULL OUTER JOIN "B_COLLECTION"."COLLECTION_CONSENT_RC" AS SUBID ON DAT."P_SERIAL_ID" = SUBID."SUBJECT_ID"
    FULL OUTER JOIN "B_TRACE"."P_TC_RC" AS TR ON TR."P_SERIAL_ID" = DAT."P_SERIAL_ID"
  WHERE DAT."STATE_ID" IN ('7','8','9')
) AS SHIT0 
WHERE shit0."SUBJECT_CITIZEN_ID" IS NOT NULL;

Переименуйте их как можно раньше, чтобы избежать ошибок и путаницы при использовании неправильного.Если вам не нужны все разные serial_no и т. Д., То, если вы определите, какой из них вы хотите во внутреннем запросе, вы можете продолжать ссылаться на него с тем же именем во внешнем запросе

Проблема в основном возникает из-за SELECT * - избегайте его использования ни для чего, кроме запросов верхнего уровня, для отладки

Использование предложения WHERE для любой таблицы с полным объединением уменьшает соединение влево /Право присоединиться.Если таблица, в которой вы находились WHERE, находится справа / слева от левого / правого соединения, соответственно отбрасывает это во внутреннее соединение:

--same as a left join b
SELECT * FROM a FULL JOIN B ON … WHERE a.id = 1

--same as a right join b
SELECT * FROM a FULL JOIN B ON … WHERE b.id = 1

--same as a inner join b
SELECT * FROM a LEFT JOIN B ON … WHERE a.id = 1
SELECT * FROM a RIGHT JOIN B ON … WHERE b.id = 1
0 голосов
/ 28 ноября 2018

Вы используете * в производной таблице и ссылаетесь на столбцы, поэтому отметьте это

SELECT "P_SERIAL_ID" 
FROM (
  SELECT TR."P_SERIAL_ID"
  FROM "B_TRACE"."P_TC_DATA" AS DAT
    FULL OUTER JOIN "B_COLLECTION"."COLLECTION_CONSENT_RC" AS SUBID ON DAT."P_SERIAL_ID" = SUBID."SUBJECT_ID"
    FULL OUTER JOIN "B_TRACE"."P_TC_RC" AS TR ON TR."P_SERIAL_ID" = DAT."P_SERIAL_ID"
  WHERE DAT."STATE_ID" IN ('7','8','9')
) AS SHIT0 
WHERE "SUBJECT_CITIZEN_ID" IS NOT NULL;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...