Как преобразовать этот подзапрос в соединение?

У меня есть следующий запрос, который работает должным образом:

SELECT insent.id, notifications.id
FROM insent
WHERE insent.id IN (
    SELECT insent_id
    FROM notifications
);

Это работает, как ожидалось, но я хочу преобразовать его в запрос с соединением. Я могу сделать это:

SELECT 
    insent.id, 
    notifications.id 
FROM insent 
JOIN notifications ON notifications.insent_id = insent.id

но поскольку для каждой входящей записи может существовать несколько записей уведомлений, это дает больше результатов, чем при первой комбинации запроса / подзапроса.

Любая идея, как я могу показать только одну отправленную запись, если для нее существует несколько записей уведомлений?

Вы можете использовать пункт DISTINCT или GROUP BY.

Sadikhasan 27.11.2018 14:51

Возможный дубликат Как использовать поле из подзапроса в MySQL?

Maksym Fedorov 27.11.2018 14:53

Поскольку вы присоединяетесь к id, значения из обеих таблиц всегда будут одинаковыми. Чего вы пытаетесь достичь, используя обе ценности? Или вас действительно интересует какое-то другое поле из таблицы insent?

Eric Brandt 27.11.2018 14:55
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
2
3
43
4

Ответы 4

Просто используйте distinct, чтобы избежать дублирования insent

SELECT distinct
    insent.id
FROM insent 
JOIN notifications ON notifications.insent_id = insent.id

Я считаю, что решение с использованием IN намного лучше. Оптимизатор запросов, скорее всего, будет использовать полусоединение.

SELECT insent.id
FROM insent
WHERE insent.id IN (
    SELECT insent_id
    FROM notifications
)

ОДНАКО, неясно, как может работать первый запрос, который вы указываете в своем вопросе? Вы не можете получить доступ к атрибуту, вложенному в подзапрос конструкции IN, из внешнего запроса.

Не уверен, что это именно то, что ищет человек, они указали, что на каждую отправленную запись приходится несколько уведомлений.

Sparky 27.11.2018 14:51

Джо Селко, автор SQL for Smarties, предлагает использовать предикат IN именно по этой причине. Вы не хотите использовать SELECT DISTINCT, потому что он использует внутренний курсор, который замедляет работу с большими наборами данных и способствует плохому дизайну. Вы буквально пытаетесь ограничить получаемые результаты тем, какие идентификаторы существуют в другой таблице. Ваш первый запрос с использованием предиката IN - лучший запрос.

Обратите внимание, что в своем первом запросе OP получает данные из таблицы notifications, которая недоступна в предложении IN(..). Так что ему в любом случае нужно присоединиться.

Madhur Bhaiya 27.11.2018 14:54

Хороший вопрос, @MadhurBhaiya. В этой ситуации его книга указывает на проблемы с нормализацией, но реальные данные не всегда соответствуют правилам;).

Paurian 27.11.2018 15:01

Можно попробовать с ROW_NUMBER

SELECT r.NotificationId,InsentId
FROM ( SELECT 
    insent.id AS InsentId, 
    notifications.id AS NotificationId,
    ROW_NUMBER () OVER ( PARTITION BY  i.id ORDER BY i.Id ) AS rn
FROM insent i
JOIN notifications n ON n.insent_id = i.id ) as r
WHERE rn=1
SELECT 
    insent.id, 
    notifications.id 
FROM insent 
JOIN (select distinct id, insent_id from notifications)notifications ON notifications.insent_id = insent.id

Другие вопросы по теме