Выбор из EAV возвращает строки дважды

У меня есть следующие таблицы

contacts
╔═══════════╦═══════════╦══════════╦═══════════╗
║ contactId ║ projectId ║ lastName ║   type    ║
╠═══════════╬═══════════╬══════════╬═══════════╣
║         1 ║         1 ║ Foo      ║ architect ║
║         2 ║         1 ║ Owner 1  ║ owner     ║
║         3 ║         1 ║ Owner 2  ║ owner     ║
╚═══════════╩═══════════╩══════════╩═══════════╝

projectDetails
╔═══════════╦═════════════╗
║ projectId ║ projectName ║
╠═══════════╬═════════════╣
║         1 ║ Bar         ║
║         2 ║ Fizz        ║
╚═══════════╩═════════════╝

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

SELECT `det`.`projectName`, `owner`.`lastName` as `ownerLast`, `architect`.`lastName` as `archLast`,
FROM `projectDetails` as `det`
LEFT JOIN `contacts` as `owner`
    ON `owner`.`projectId` = `det`.`projectId` AND `owner`.`type` = "owner"
LEFT JOIN `contacts` as `architect`
    ON `architect`.`projectId` = `det`.`projectId` AND `architect`.`type` = "architect"
WHERE `architect`.`lastName` = "Foo"

Это генерирует две строки

╔═════════════╦═══════════╦══════════╗
║ projectName ║ ownerLast ║ archLast ║
╠═════════════╬═══════════╬══════════╣
║ Bar         ║ Owner1    ║ Foo      ║
║ Bar         ║ Owner2    ║ Foo      ║
╚═════════════╩═══════════╩══════════╝

Что, я полагаю, имеет смысл, но это не то, что я ищу. Есть ли способ объединить результаты одного типа, например, во что-то вроде

╔═════════════╦════════════════╦══════════╗
║ projectName ║   ownerLast    ║ archLast ║
╠═════════════╬════════════════╬══════════╣
║ Bar         ║ Owner1, Owner2 ║ Foo      ║
╚═════════════╩════════════════╩══════════╝

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

Strawberry 26.10.2018 14:28

Кроме того, ваше второе соединение является внутренним, что можно проиллюстрировать, выполнив EXPLAIN EXTENDED [YOUR QUERY], а затем SHOW WARNINGS;.

Strawberry 26.10.2018 14:29

Да, и ваш запрос явно недействителен, так что вы не совсем правду!

Strawberry 26.10.2018 14:31

@ Strawberry, я по ошибке оставил запятую в конце моего запроса SELECT. Прости за это. Я, вероятно, сделаю это на php, спасибо за ваш комментарий.

Constantine Loukas 26.10.2018 16:45
Освоение архитектуры микросервисов с 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
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
4
61
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Используйте group_concat()

SELECT `det`.`projectName`, group_concat(`owner`.`lastName`) as `ownerLast`, `architect`.`lastName` as `archLast`,
FROM `projectDetails` as `det`
LEFT JOIN `contacts` as `owner`
    ON `owner`.`projectId` = `det`.`projectId` AND `owner`.`type` = "owner"
LEFT JOIN `contacts` as `architect`
    ON `architect`.`projectId` = `det`.`projectId` AND `architect`.`type` = "architect"
WHERE `architect`.`lastName` = "Foo"
group by `det`.`projectName`,`architect`.`lastName`

использовать group_concat()

SELECT `det`.`projectName`, group_concat( `owner`.`lastName`) as `ownerLast`, `architect`.`lastName` as `archLast`,
FROM `projectDetails` as `det`
LEFT JOIN `contacts` as `owner`
    ON `owner`.`projectId` = `det`.`projectId` AND `owner`.`type` = "owner"
LEFT JOIN `contacts` as `architect`
    ON `architect`.`projectId` = `det`.`projectId` AND `architect`.`type` = "architect"
WHERE `architect`.`lastName` = "Foo"
group by `det`.`projectName`,archLast

Это работает как шарм, спасибо. Как бы вы его изменили, если бы хотели проверить, есть ли у ЛЮБОГО типа в таблице contacts повторяющаяся строка. Я попытался добавить group_concat (architect.lastName), а затем также сгруппировать по owner.lastName, но он вернулся к возврату двух строк.

Constantine Loukas 26.10.2018 11:00

@ConstantineLoukas на самом деле не будет дублироваться, потому что это поле находится в группе по предложению

Zaynul Abadin Tuhin 26.10.2018 11:50

Извините, я неправильно объяснил. Допустим, у вас было 10 проектов, у некоторых было 2 владельца, у некоторых 2 архитектора, у некоторых 1 владелец и 1 архитектор, а у некоторых только 1 владелец или 1 архитектор. Есть ли способ изменить приведенный выше запрос, чтобы учесть это, или я должен просто запросить все контакты для этого проекта, а затем выполнить любую группировку на уровне приложения с помощью php?

Constantine Loukas 26.10.2018 12:49

@ConstantineLoukas Вы должны сменить WHERE на AND

Strawberry 26.10.2018 14:33

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