Запросить другие поля в таблицах, на которые ссылается FK в соединительной таблице.

У меня есть "соединительная" таблица (recipe_ingredients), которую я использую для обработки отношений "многие ко многим" в моей базе данных. Каждое поле в этой таблице является ссылкой на PK другой таблицы: recipe_id, ingredient_id, quantity_id и measure_id. Это ПК таблиц metadata, ingredients, quantities и measurements. За исключением таблицы metadata, все эти таблицы имеют только два поля: ПК и имя или номер, связанные с этим ПК.

Я пытаюсь запросить recipe_ingredients для всех строк с данным recipe_id... но вместо отображения ПК в каждой строке с этим recipe_id я хочу отобразить имя/номер, связанный с этим ПК в этой таблице.

Итак, вместо запроса, который возвращает это:

recipe_id | ingredient_id | quantity_id | measure_id
----------+---------------+-------------+-----------
1         | 10            | 2           | 3
----------+---------------+-------------+-----------
1         | 12            | 2           | 3
----------+---------------+-------------+-----------
1         | 13            | 5           | 6
----------+---------------+-------------+-----------
...

Я ищу запрос, который возвращает что-то вроде этого:

recipe_id | ingredient_name | quantity_num | measure_num
----------+-----------------+--------------+------------
1         | Ground cayenne  | 1/2          | tsp
----------+-----------------+--------------+------------
1         | Ground paprika  | 1/2          | tsp
----------+-----------------+--------------+------------
1         | Olive oil       | 1            | tbsp
----------+-----------------+--------------+------------
...

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

Я использую sqlite3 в Debian.

Таблица "соединений" recipe_ingredients:

CREATE TABLE recipe_ingredients (
    recipe_id               int,
    ingredient_id           int,
    quantity_id             int,
    measure_id              int,
    primary key (recipe_id, ingredient_id),
    foreign key (recipe_id)
            references metadata (recipe_id)
                    on update restrict
                    on delete restrict,
    foreign key (ingredient_id)
            references ingredients (ingredient_id)
                    on update restrict
                    on delete restrict,
    foreign key (quantity_id)
            references quantities (quantity_id)
                    on update restrict
                    on delete restrict,
    foreign key (measure_id)
            references measurements (measure_id)
                    on update restrict
                    on delete restrict
);

Это сторонние таблицы, на которые ссылается соединительная таблица:

create table if not exists ingredients (
    ingredient_id           integer         primary key,
    ingredient_name         text            not null
);

create table if not exists quantities (
    quantity_id             integer         primary key,
    quantity_num            int             not null
);

create table if not exists measurements (
    measure_id              integer         primary key,
    measure_name            text            not null
);

create table if not exists metadata (
    recipe_id               integer         primary key,
    recipe_name             text            not null,
    course_id               int,
    cuisine_id              int,
    servings                int,
    prep_time               int,
    cook_time               int,
    total_time              int,
    foreign key (course_id)
            references courses (course_id)
                    on update restrict
                    on delete restrict,
    foreign key (cuisine_id)
            references cuisine (cuisine_id)
                    on update cascade
                    on delete cascade
);

person Nickolas Peter O'Malley    schedule 18.02.2020    source источник
comment
Вы, должно быть, видели, как это делается в каком-то примере какого-нибудь введения. Также это дубликат. Чего следует ожидать в качестве основного вопроса. Прежде чем рассматривать публикацию, пожалуйста, всегда гуглите любое сообщение об ошибке или множество четких, кратких и точных формулировок вашего вопроса/проблемы/цели, с вашими конкретными строками/именами и тегами site:stackoverflow.com и без них; прочитал много ответов. Если вы публикуете вопрос, используйте одну фразу в качестве заголовка. См. раздел Как задать вопрос и тексты при наведении указателя мыши на стрелку голосования.   -  person philipxy    schedule 19.02.2020


Ответы (1)


Вы можете join соединять таблицу с каждой из связанных таблиц следующим образом:

select
    ri.recipe_id,
    i.ingredient_name,
    q.quantity_num,
    m.measure_num
from recipe_ingredients ri
inner join ingredients i  on i.ingredient_id = ri.ingredient_id
inner join quantities q   on q.quantity_id = ri.quantity_id
inner noin measurements m on m.measure_id = ri.measure_id
where ri.recipe_id = ?

Знак вопроса (?) означает recipe_id, который вы ищете.

person GMB    schedule 18.02.2020
comment
Это работает, спасибо! Мне просто использовать inner join вместо join, чтобы запрос возвращал только совпадающие данные из обеих таблиц? - person Nickolas Peter O'Malley; 18.02.2020
comment
@NickolasPeterO'Malley: inner join и join на самом деле являются синонимами (они делают одно и то же). Вероятно, вы ссылаетесь на left join, который не устраняет несовпадающие записи с правой стороны join. - person GMB; 19.02.2020