Присоединение к таблице, но обеспечение возврата всех строк из первой таблицы - PullRequest
1 голос
/ 02 августа 2020

У меня есть система хранения почтовой информации в PostgreSQL. У нас есть таблица postal_carriers, в которой содержится информация о перевозчике. У нас есть таблица postal_zones, в которой хранятся зоны для postal_carriers. У нас есть таблица countries с информацией о стране. Теперь я создал таблицу postal_zone_mapping, в которой страны сопоставляются с зонами разных операторов связи. Вот определение для этого.

CREATE TABLE shopman.postal_zone_mapping
(
    postal_zone_id integer,
    postal_carrier_id integer,
    country_id integer,
    CONSTRAINT pzm_key UNIQUE (country_id, postal_carrier_id),
    CONSTRAINT pzm_fkey FOREIGN KEY (country_id)
        REFERENCES shopman.countries (country_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT postal_zone_mapping_postal_carrier_id_fkey FOREIGN KEY (postal_carrier_id)
        REFERENCES shopman.postal_carriers (postal_carrier_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION,
    CONSTRAINT postal_zone_mapping_postal_zone_id_fkey FOREIGN KEY (postal_zone_id)
        REFERENCES shopman.postal_zones (postal_zone_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)

Это оператор, который я использую для выбора данных, выбирая таблицу country с левым соединением в таблице postal_zone_mapping, так как я хочу, чтобы все страны, указанные для оператора связи, независимо от того, сопоставлены они с конкретным оператором и зоной или нет.

    SELECT c.country_id,
           COALESCE(postal_zone_id,-1) AS postal_zone_id,
           COALESCE(postal_carrier_id,-1) AS postal_carrier_id,
           country_name
      FROM shopman.countries c 
           LEFT JOIN shopman.postal_zone_mapping p 
                  ON c.country_id=p.country_id
     WHERE postal_carrier_id=1 
        OR postal_carrier_id IS NULL 
     ORDER BY country_name ASC 
    OFFSET 0 ROWS FETCH FIRST 50 ROWS ONLY

Я хочу, чтобы этот запрос возвращал каждую страну, идентификатор оператора связи, если он соответствует тому, который мы хотим вместе с идентификатор зоны, но с моим запросом, если мы вставим карту для оператора, то в возвращаемых результатах не будет этой страны. Где я ошибаюсь в своем запросе? Кроме того, есть ли лучший способ достичь этого сопоставления? Я пошел по этому пути, чтобы избежать необходимости динамически добавлять столбцы или иметь массивы.

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

Для справки, вот определение других таблиц:

CREATE TABLE shopman.postal_carriers
(
    postal_carrier_id serial,
    postal_carrier_name text,
    description text,
    CONSTRAINT postal_carriers_pkey PRIMARY KEY (postal_carrier_id),
    CONSTRAINT postal_carriers_postal_carrier_name_key UNIQUE (postal_carrier_name)
)

CREATE TABLE shopman.postal_zones
(
    postal_zone_id serial,
    postal_carrier_id integer,
    postal_zone_name text,
    CONSTRAINT postal_zones_pkey PRIMARY KEY (postal_zone_id),
    CONSTRAINT postal_zones_postal_zones_name_key UNIQUE (postal_carrier_id, postal_zone_name),
    CONSTRAINT postal_zones_postal_carrier_id_fkey FOREIGN KEY (postal_carrier_id)
        REFERENCES shopman.postal_carriers (postal_carrier_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)

CREATE TABLE shopman.countries
(
    country_id serial,
    country_name text,
    code_2 text",
    code_3 text,
    region_id integer,
    CONSTRAINT countries_pkey PRIMARY KEY (country_id),
    CONSTRAINT countries_code_2_key UNIQUE (code_2),
    CONSTRAINT countries_code_3_key UNIQUE (code_3),
    CONSTRAINT countries_name_key UNIQUE (country_name),
    CONSTRAINT countries_region_id_fkey FOREIGN KEY (region_id)
        REFERENCES shopman.regions (region_id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE NO ACTION
)

1 Ответ

3 голосов
/ 02 августа 2020

Переместите условие из таблицы second в предложение ON:

SELECT c.country_id,
       COALESCE(p.postal_zone_id, -1) AS postal_zone_id,
       COALESCE(p.postal_carrier_id,-1) AS postal_carrier_id,
       c.country_name
FROM shopman.countries c LEFT JOIN
     shopman.postal_zone_mapping p 
     ON c.country_id = p.country_id AND p.postal_carrier_id = 1 
ORDER BY c.country_name ASC 
OFFSET 0 ROWS FETCH FIRST 50 ROWS ONLY
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...