MySQL выберите запрос из объединенной таблицы, имеющий точное количество дочерних строк

У меня есть две таблицы, как показано ниже.

PermissionAccessEntities


peID      |   petID
-------------------
1         |   1
2         |   4
3         |   1
4         |   2
5         |   4
6         |   4
-------------------

PermissionAccessEntityGroups


pegID     |   peID     |  gID
-----------------------------
1         |   5        |  1
2         |   5        |  2
3         |   5        |  3
4         |   6        |  2
5         |   6        |  3
-----------------------------

Теперь у меня есть запрос доктрины getOne, как показано ниже:

select pae.peID from PermissionAccessEntities pae 
left join PermissionAccessEntityGroups paeg1 on pae.peID = paeg1.peID 
left join PermissionAccessEntityGroups paeg2 on pae.peID = paeg2.peID 
where petID = 4 and paeg1.gID = 2 and paeg2.gID = 3;

Что возвращает 5 и 6. Но я хочу получить результат с точным количеством совпадающих строк. В данном случае это 6.

Есть ли способ использовать JOIN для получения того же набора результатов, что и выше?

Помощь очень ценится.

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

Nick 25.10.2018 04:25

К сожалению, данные в таблице неверны. Починил это.

biplob 25.10.2018 05:34

Что вы подразумеваете под «точным количеством совпадающих строк»? Я не вижу разницы в результатах для peID=5 и peID=6.

Nick 25.10.2018 05:43

@Nick есть одна дополнительная строка gID = 1 для peID = 5. Кажется, что OP хочет учитывать только те значения peID, которые имеют gID = 2 and 3 only

Madhur Bhaiya 25.10.2018 06:10

Итак, peID=5 имеет 3 gID=(1,2,3) и peID=6 имеет 2 gID=(2,3). Я хочу получить только peID=6, а не peID=5.

biplob 25.10.2018 06:10

@MadhurBhaiya, ты прав.

biplob 25.10.2018 06:11

@CoderBoy проверьте обновленный опубликованный ответ

Madhur Bhaiya 25.10.2018 06:16
Освоение архитектуры микросервисов с 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
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
7
50
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий
  • Состояние Where в этом случае вам не поможет. Потому что вы хотите учитывать количество всех строк для дальнейшей фильтрации. Вам нужно будет использовать Group By с условной фильтрацией с помощью предложения Having.
  • Мы также можем упростить запрос, чтобы использовать только одно соединение с таблицей PermissionAccessEntityGroups.
  • Функция Count() используется для подсчета количества строк в группе. Мы также можем использовать Sum( conditional statements ) для подсчета количества строк, соответствующих условию. Условный оператор вернет 1 для совпадающих строк и 0 для несовпадающих строк.

Вместо этого попробуйте следующий запрос:

SELECT pae.peID 
FROM PermissionAccessEntities AS pae 
LEFT JOIN PermissionAccessEntityGroups AS paeg 
  ON pae.peID = paeg.peID 
WHERE pae.petID = 4
GROUP BY pae.peID
HAVING COUNT(*) = SUM(paeg.gID IN (2,3))

DB Fiddle DEMO


Теперь вспомните, что Count(NULL) = 0; однако COUNT(0) = COUNT(1) = 1. Итак, другой способ написать этот запрос с использованием только функции Count():

SELECT pae.peID 
FROM PermissionAccessEntities AS pae 
LEFT JOIN PermissionAccessEntityGroups AS paeg 
  ON pae.peID = paeg.peID 
WHERE pae.petID = 4
GROUP BY pae.peID
HAVING COUNT(*) = COUNT(CASE WHEN paeg.gID IN (2,3) THEN 1 END)

DB Fiddle DEMO 2

Возвращает тот же результат, что и исходный запрос OP

Nick 25.10.2018 06:08

@Nick нет, это не так. У тебя есть рабочий пример? OP изменил данные впоследствии

Madhur Bhaiya 25.10.2018 06:09

Да, у меня есть рабочий пример, и с новыми данными OPs ваш запрос дает точно такой же результат, как исходный запрос OP. Отсюда мой второй комментарий к вопросу.

Nick 25.10.2018 06:10

@MadhurBhaiya & Nick Да, обновленный работает. Большое спасибо.

biplob 25.10.2018 06:21

Вы можете достичь желаемого результата, сначала посмотрев записи, соответствующие (2,3), а затем проверив, соответствует ли какая-либо из них одному из других значений. Все, что не соответствует (paeg2.peID IS NULL), является точным совпадением:

SELECT DISTINCT(pae.peID)
FROM PermissionAccessEntities pae 
JOIN PermissionAccessEntityGroups paeg1 ON paeg1.peID = pae.peID AND paeg1.gID IN (2,3)
LEFT JOIN PermissionAccessEntityGroups paeg2 ON paeg2.peID = pae.peID AND paeg2.gID NOT IN (2,3)
WHERE pae.petID = 4 AND paeg2.peID IS NULL

Демо на dbfiddle

другой подход. Думаю, нужно еще и where pae.petID = 4 поставить. +1

Madhur Bhaiya 25.10.2018 06:25

@Nick Думал, что все работает нормально, мне интересно, как это будет работать для более чем двух строк? Например, у меня есть gID=1,2,3,4, и я хочу найти gID=1,2,3. Тогда нам нужно еще одно соединение?

biplob 25.10.2018 06:39

@CoderBoy просто измените условия IN на IN (1,2,3) и NOT IN (1,2,3)

Nick 25.10.2018 07:04
SELECT pae.peID FROM PermissionAccessEntities pae 
INNER JOIN PermissionAccessEntityGroups paeg1 ON  pae.peID=paeg1.peID
WHERE pae.petID = 4 AND paeg1.peID NOT IN (SELECT DISTINCT peID FROM 
PermissionAccessEntityGroups WHERE gID NOT IN (2,3));

Спасибо за Ваш ответ. Он возвращает 6, но две записи.

biplob 25.10.2018 06:48

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