Postgresql - как получить записи в таблице, которые не имеют соответствия в другой таблице

У меня есть вопрос, но я действительно не знаю, как его спросить! Пожалуйста, не стесняйтесь:

SELECT      sc.*, 
        scd.siteid, scd.desc_frontend
FROM        shipping_code sc
LEFT OUTER JOIN shipping_code_description scd
    ON          scd.shippingid=sc.shippingid
    AND         scd.siteid IN (SELECT siteid FROM site_international WHERE published='t')

Чтобы объяснить это, у нас есть коды доставки (доставки) в одной таблице, называемые "shipping_code", и, поскольку у нас есть многоязычный сайт, у нас есть другая таблица для описания языков этих кодов в "shipping_code_description". У нас также есть таблица под названием "site_international", которая имеет следующие поля: "siteid" (идентификатор сайта - например, для Великобритании, DE, FR.. (английский, немецкий, французский) и "опубликованный" (логическое поле, т.е. сайт жив или нет?)

Вышеприведенный запрос SELECT получает все коды доставки с указанием их описания только для опубликованных сайтов.

Теперь мы также хотим знать, какие коды доставки НЕ содержат описания на определенных сайтах. Если код доставки совершенно новый, тогда для этого кода будет возвращена 1 строка (из-за LEFT OUTER JOIN). "Scd.siteid" и "scd.desc_frontend" будут NULL.

Однако, если описание для британского (английского) сайта существует, но описания для FR и DE не существует, то вышеупомянутый запрос будет просто возвращать одну строку, а не три строки. Как я могу сказать, что описания DE и FR отсутствуют для определенного кода доставки?

Вот мои варианты:

1) Я мог бы как-то сделать все это в одном запросе. Должен быть способ (Я никогда раньше не использовал UNION, EXCEPT и т.д., И я не уверен, что это то, что я должен использовать).

2) ИЛИ я мог просто сделать другой запрос   SELECT siteid FROM site_international WHERE опубликовано = 't'

и выше сказанное дало бы мне все опубликованные сайты. Затем, используя PHP (который я использую для кодирования моего сайта), для каждого результата вышеуказанного более крупного запроса я бы проверил и посмотрел, отсутствуют ли описания. Например. Вышеупомянутый запрос siteid вернет 3 идентификатора (Великобритания, DE, FR). Затем, если для определенного кода доставки возвращается только одна строка в Великобритании, я бы знал, что DE и FR отсутствуют, и я могу отметить это для моего клиента.

Пожалуйста, сообщите, существует ли лучший вариант "1"?

Большое спасибо!

Ответы

Ответ 1

Возможно, я не понимаю ваш вопрос, но если вы хотите получить "записи в таблице, которые не имеют соответствия в другой таблице", я могу дать вам простой фрагмент.

Выберите все строки из левой таблицы, которые не находятся в правой таблице.

SELECT  l.*
FROM    t_left l
LEFT JOIN t_right r
ON      r.value = l.value
WHERE   r.value IS NULL

Ответ 2

Я думаю, что это то, что вы ищете. Left Join получает все возможные коды кода доставки и кода сайта, затем он обнаруживает, у кого из них нет записи в таблице "Описания". Это то, что делает предложение Exists.

SELECT      
    Shipping_Code.*,
    Site_International.SiteID 
FROM        
    Shipping_Code 
    LEFT JOIN Site_International ON Site_International.Published = 't'
WHERE
    NOT EXISTS (
        SELECT
            NULL
        FROM
            Shipping_Code_Description
        WHERE
            Shipping_Code.ShippingID = Shipping_Code_Description.ShippingID
        AND SiteInternational.SiteID = Shipping_Code_Description.SiteID)