Создание отношений 1: n (один-ко-многим) или n:1 (многие-к-одному)
Содержание:
- Общие нюансы для связей
- Бонус
- Создание и изменение отношений 1:N между сущностями
- Связь один-к-одному
- Ассоциация ManyToOne / OneToMany.
- Элемент области навигации для основной сущности
- Целостность данных
- Один к одному (one-to-one)
- Поведение отношений
- Связь 1-N — один ко многим
- Связь «Один ко многим»
- Извлечение данных для связи «многие ко многим» (SELECT)
Общие нюансы для связей
- В контексте процесса доступно только два варианта связей 1-1 и 1-N (особенность контекста процесса, потому что доступно редактирование контекста без перезагрузки ELMA, но это уже другая история)
- Будьте аккуратны с копированием свойств — списков:
- 1-N — при копировании проверяйте ключевую колонку
- если запустить «как есть» будет общая связь для разных свойств — что в последствии нарушит целостность базы данных (будут битые связи) и при перестроении базы данных — система не запустится — бомба замедленного действия (починить можно — как расскажу в следующий раз)
- если открыть свойство на редактирование — ключевая колонка будет пустой и потребуется ее заполнить — тогда все будет хорошо
- N-N — при копировании проверяйте название развязочной таблицы
- если запустить «как есть» будет общая развязочная таблица для разных свойств — будут путаться списки и в последствии нарушится целостность базы данных и при перестроении базы данных ELMA не запустится — снова бомба замедленного действия
- если открыть свойство на редактирование — система не даст сохранить развязочную таблицу с наименованием, которое уже есть в системе — тогда все будет хорошо
- N-N (инверсия) — при копировании проверяйте ключевую колонку, как с 1-N — последствия те же
- 1-N — при копировании проверяйте ключевую колонку
- Не приравнивайте в коде один список к другому
- нельзя писать Клиент1.Заказы = Клиент2.Заказы, при сохранении будет ошибка — найдены общие связи коллекций
- нужно писать Клиент1.Заказы.AddAll( Клиент2.Заказы)
- В объектах ELMA BPM разработчики решили даже в незаполненных объектах создавать пустые коллекции
- Для создания списков — старайтесь не использовать блоки, тем более если элемент списка — независимый объект.(иногда для создания списка новички создают блок с одним свойством (получается развязочная таблица) — знайте это костыль
Бонус
Списки можно вывести таблицей — выведите на форму «Список связанных сущностей»
- со связями 1-N и N-N(инверсия) можно указать ключевую колонку и получится удобная таблица:
- со связью N-N придется заморочиться и придумать EQL вот из статья базы знаний
Создание и изменение отношений 1:N между сущностями
Откройте обозреватель решений.
В разделе Компоненты раскройте узел Сущности, затем раскройте сущность, с которой требуется работать.
Выберите Отношения 1:N.
Чтобы изменить отношение или просмотреть сведения для отношения, выберите отношение и нажмите на панели инструментов «Действия» кнопку Другие действия, затем выберите Изменить.
— ИЛИ —
Чтобы добавить новое отношение, выберите Создать отношение «один ко многим».
Важно!
Если кнопка Создать отношение «один ко многим» не отображается на панели инструментов «Действия», то создать отношение 1:N для этой сущности невозможно.
Для нового отношения в разделе Определение отношения выберите в списке Связанная сущность сущность для связывания.
Примечание
При указании связанной сущности задается значение по умолчанию в поле Имя. Если изменить связанную сущность перед ее сохранением, соответственно изменится и значение поля Имя.
Выберите, будет ли это поле доступно для поиска или нет.
В разделе Поле поиска укажите значение для поля в поле Отображаемое имя.
Важно!
При указании значения Отображаемое имя задается значение по умолчанию в поле Имя
Если изменить Отображаемое имя поля поиска перед сохранением данных, значение в поле Имя не изменится. Поэтому необходимо ввести в поле Имя информативное значение перед сохранением данных.
В списке Требование поля выберите вариант, чтобы указать требования к данным для поля перед сохранением записи.
В разделе Элемент области переходов для основной сущности в списке Параметры отображения выберите вариант отображения связанных представлений для пользовательской метки.
В разделе Поведение отношений выберите в списке Тип отношений один из следующих вариантов.
Родительское. В родительском отношении между двумя сущностями любое действие, выполняемое над записью основной (родительской) сущности, также выполняется над всеми связанными с ней записями дочерних сущностей.
Ссылочное. При ссылочном отношении между двумя сущностями можно переходить к любым связанным записям, но действия, выполняемые над одной записью, не применяются к другим.
Ссылочное с ограниченным удалением. В ссылоном отношении с ограничением удаления можно переходить к любым связанным записям. Действия, выполняемые над родительской записью, не будут выполняться над дочерней, но пока она существует, удалить родительскую запись будет невозможно. Учтите, что запись нельзя удалить, если имеются связанные с ней записи.
Настраиваемое каскадное. В настраиваемом каскадном отношении между двумя сущностями выбирается поведение, связанное с каждым из наборов возможных действий.
Важно!
Если выбрать поведения для действий, совпадающие с поведениями для действий, связанными с другим Типом поведения, то при сохранении отношения значение Тип поведения будет автоматически установлено равным такому совпадающему типу.
Дополнительные сведения:
-
Выберите Сохранить и закрыть, чтобы закрыть форму Отношение.
-
Выполнив настройки, опубликуйте их:
-
Чтобы опубликовать настройки только для компонента, изменяемого в данный момент, на панели инструментов «Действия» выберите Опубликовать.
-
Чтобы опубликовать настройки для всех неопубликованных компонентов одновременно, на панели навигации или в области переходов выберите Сущности, затем на панели инструментов «Действия» выберите Опубликовать все настройки.
-
Примечание
- Настраиваемая сущность не может быть основной в каскадном отношении со связанной системной сущностью. Это означает, что между основной настраиваемой сущностью и связанной системной сущностью не может быть отношений с каким-либо из действий, установленным в «Передавать всем», «Передавать активным» или «Передавать владельцу».
- У новых отношений действие не может иметь значение Передавать всем, Передавать активным или Передавать владельцу, если связанная сущность в этом отношении уже является связанной сущностью в любом другом отношении, действие которого имеет значение Передавать всем, Передавать активным или Передавать владельцу. Это позволяет избежать создания отношений с несколькими родительскими сущностями.
- После каждого изменения элементов пользовательского интерфейса или внедрения скриптов формы для сущности необходима публикация изменений. Все изменения в схеме данных приложения, таких как настраиваемые сущности, связи или поля, применяются сразу.
- Если отношение является частью управляемого решения, разработчик решения может ограничить настройку отношения пользователями.
- Установка решения или публикация настроек может помешать нормальной работе системы. Рекомендуется запланировать импорт решения в оптимальный для пользователей период.
Связь один-к-одному
Последнее обновление: 17.05.2019
Отношение один к одному указывает, что одна сущность может владеть другой сущностью в единственном экземпляре. Например, у команды может быть только один тренер. С другой стороны,
тренер может тренировать одновременно только одну команду.
Для создания подобной связи между моделями применяется метод hasOne(). Например, определим модели тренера и команды:
const Sequelize = require("sequelize"); const sequelize = new Sequelize("game", "root", "123456", { dialect: "mysql", host: "localhost", define: { timestamps: false } }); const Coach = sequelize.define("coach", { id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false }, name: { type: Sequelize.STRING, allowNull: false } }); const Team = sequelize.define("team", { id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true, allowNull: false }, name: { type: Sequelize.STRING, allowNull: false } }); Coach.hasOne(Team, { onDelete: "cascade"}); sequelize.sync({force:true}).then(()=>{ console.log("Tables have been created"); }).catch(err=>console.log(err));
В данном случае модель тренера (Coach) условно считается главной, а модель команды (Team) зависимой (но в данном случае деление на главную и зависимую модель
достаточно условно). Поэтому метод вызывается у модели Coach, и в качестве первого параметра передается модель Team. Хотя в данном случае не имеет значения, какая именно модель является главной или зависимой.
Второй параметр метода задает конфигурацию связи, в частности, каскадное удаление.
В итоге при выполнении данного когда в MySQL будут созданы следующие таблицы:
CREATE TABLE `coaches` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf-8 COLLATE=utf8mb4_0900_ai_ci; CREATE TABLE `teams` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL, `coachId` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `coachId` (`coachId`), CONSTRAINT `teams_ibfk_1` FOREIGN KEY (`coachId`) REFERENCES `coaches` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf-8 COLLATE=utf8mb4_0900_ai_ci;
Как мы видим, в таблице teams создается дополнительный столбец coachId, через который данная таблица будет связана с таблицей coaches.
Добавление и получение связанных данных
Для установки связанных данных применяется метод setНАЗВАНИЕ_МОДЕЛИ(). Например, добавим тренера и его команду:
// добавляем тренера Coach.create({ name: "Tom Smith"}) .then(coach=>{ // Добавляем команду Team.create({name:"Real Madrid"}).then(team=>{ // устанавливаем для тренера команду coach.setTeam(team).catch(err=>console.log(err)); }); }).catch(err=>console.log(err));
По факту метод будет вызывать SQL-команду UPDATE. То есть к моменту вызова данного метода связываемые сущности уже должны быть в
базе данных.
Для получения связанных данных применяется метод getНАЗВАНИЕ_МОДЕЛИ(). Например, получим тренера и его команду:
// получаем тренера с id=1 Coach.findByPk(1).then(coach=>{ if(!coach) return console.log("Coach not found"); coach.getTeam().then(team=>{ console.log(coach.name, "-", team.name); }); });
В данном случае на консоли мы получим:
Tom Smith - Real Madrid
Получение всех тренеров с включением связанных данных:
Coach.findAll({ attributes: , // включаем столбец name из таблицы coaches include: // включаем столбец name из таблицы teams }] }).then(coaches => { for(coach of coaches){ console.log(coach.name, "-", coach.team.name); } });
НазадВперед
Ассоциация ManyToOne / OneToMany.
Предположим, что каждый продукт в вашей заявке относится только к одной категории. В этом случае вам понадобится класс Category и способ связать объект Product объектом Category.
Начните с создания Category с полем name:
php bin/console make:entity Category New property name (press <return> to stop adding fields): > name Field type (enter ? to see all types) : > string Field length : > 255 Can this field be null in the database (nullable) (yes/no) : > no New property name (press <return> to stop adding fields): > (press enter again to finish)
Это сгенерирует ваш новый класс сущности:
// src/Entity/Category.php // ... class Category { /** * @ORM\Id * @ORM\GeneratedValue * @ORM\Column(type="integer") */ private $id; /** * @ORM\Column(type="string") */ private $name; // ... getters and setters }
Элемент области навигации для основной сущности
Можно показать списки связанных сущностей в основной сущности, развернув панель навигации. С помощью параметров в этой группе можно управлять тем, что будет отображаться в этом списке и будет ли что-то отображаться вовсе. Следующие элементы навигации можно изменить с помощью редактора форм, а с помощью JavaScript разработчик может внести изменения в эти элементы, если отображается форма.
Поле | Описание |
---|---|
Параметры отображения | — Не отображать. Выберите этот параметр, требуется запретить пользователям переходить к списку записей связанных сущностей.- Использовать специальные метки. Выберите этот параметр, если требуется указать специальную метку для использования.- Использовать имя во множественном числе. Выберите этот параметр, если имя связанной сущности во множественном числе требуется использовать в качестве метки. |
Пользовательская метка | При выборе параметра Использовать специальные метки в качестве параметра отображения введите специальную метку, которую требуется использовать вместо имени связанной сущности во множественном числе. |
Область отображения | — Сведения. Выберите этот параметр для включения элемента навигации в группу Общие.- Маркетинг. Выберите этот параметр для включения элемента навигации в группу Маркетинг.- Продажи. Выберите этот параметр для включения элемента навигации в группу Продажи.- Служба. Выберите этот параметр для включения элемента навигации в группу Служба. |
Порядок отображения | Это значение управляет тем, будет ли элемент навигации включен в выбранную область отображения. Диапазон доступных номеров начинается с 10 000. Элементы области навигации с меньшим значением будут стоять в списке выше других отношений. |
Целостность данных
Референтная целостность — это система правил, которую использует Access, чтобы убедиться, что связи между записями в соответствующих таблицах действительны и что пользователь не удалит или не изменит случайно связанные с ними данные. Вы можете установить целостность данных, когда все следующие условия верны:
- Совпадающие поля из основной таблицы являются первичным ключом или имеет уникальный индекс.
- Связанные поля имеют один и тот же тип данных. Из этого правила есть два исключения: Поле AutoNumber может быть связано с полем Number, которое имеет настройку свойства Long Integer, а поле AutoNumber, которое имеет настройку свойства Replication ID, может быть связано с полем Number, которое имеет настройку свойства Replication ID.
- Обе таблицы относятся к одной и той же базе данных Access. Если таблицы являются связанными таблицами, они должны быть таблицами в формате Access, и необходимо открыть базу данных, в которой они хранятся, чтобы установить целостность данных. Референтная целостность не может быть применена для связанных таблиц из баз данных в других форматах.
При использовании целостности данных применяются следующие правила:
- Невозможно ввести значение во внешнем ключевом поле связанной таблицы, которое не существует в первичном ключе первичной таблицы. Тем не менее, можно ввести значение Null во внешнем ключе. Это указывает на то, что записи не связаны между собой. Например, невозможно иметь заказ, который назначается клиенту, который не существует. Тем не менее, можно иметь заказ, который не назначается никому, введя значение Null в поле CustomerID.
- Вы не можете удалить запись из основной таблицы, если в соответствующей таблице существуют соответствующие записи. Например, вы не можете удалить запись сотрудника из таблицы «Сотрудники», если в таблице «Заказы» есть заказы, назначенные сотруднику.
- Невозможно изменить основное ключевое значение в основной таблице, если эта запись имеет соответствующие записи. Например, вы не можете изменить идентификатор сотрудника в таблице «Сотрудники», если в таблице «Заказы» есть заказы, назначенные этому сотруднику.
Один к одному (one-to-one)
Связь один к одному это когда одной записи в таблице отвечает только одна запись из другой таблицы. Чтобы продемонстрировать связь один к одному возьмем таблицу supplier:
и вынесем колонку full_address в отдельную таблицу. Таким образом в таблице supplier будет ссылка на таблицу address, в которой будут такие поля: address_id, coutry, city, street.
Не теряя времени сделаем нужные изменения.
alter table supplier modify column full_address int;
Так как поле full_address будет ссылкой на таблицу address сделаем его тип целочисленным.
Далее создадим саму таблицу address.
create table address(address_id int auto_increment primary key, country text, city text, street text);
Теперь укажем, что поле full_address будет внешним ключом:
alter table supplier add foreign key (full_address) references address(address_id);
Связь один к одному означает, что в таблице supplier будет уникальный идентификатор записи с таблицы address. Поэтому, нужно сделать поле full_address уникальным:
alter table supplier add foreign key (full_address) references address(address_id);
Теперь, каждый адрес будет относиться только к одному поставщику и все попытки добавить поставщику адрес другого поставщика будет приводить к ошибке.
Поведение отношений
Можно настроить поведение отношения 1:N для поддержки бизнес-правил организации. Почему это может потребоваться? Рассмотрим пример.
Допустим, у вас новый продавец и требуется назначить ему несколько существующих возможных сделок, в данное время назначенных другому продавцу. Каждая запись возможной сделки может иметь несколько действий задач, связанных с ней. Можно легко найти активные возможные сделки, которые требуется переназначить, и назначить их новому продавцу. Но что произойдет с действиями задач, связанными с возможными сделками? Хотелось бы вам открывать каждую задачу и указывать, должна ли она также быть назначена новому продавцу? Скорее всего, нет. Вместо этого можно разрешить отношению применить некоторые стандартные правила автоматически. Эти правила применяются только к записям задач, связанным с возможными сделками, которые вы переназначаете. Это отношение сущностей называется Opportunity_Tasks. Можно выполнить следующие действия:
-
Переназначить все активные задачи.
-
Переназначить все задачи. Это поведение принимается по умолчанию.
-
Не переназначать задачи.
-
Переназначить все задачи, которые в данный момент назначены бывшему владельцу возможной сделки.
Отношение может управлять тем, как действия, выполняемые с записью для записи основной сущности, распространяются на все записи связанной сущности. Действия и возможное поведение приведены в следующей таблице.
Действие | Описание | Возможное поведение |
---|---|---|
Назначение | Что должно произойти, когда меняется владелец записи основной сущности? | — Каскад для активных- Каскад для всех- Без каскадных- Каскад для ответств. |
Общий доступ | Что должно произойти при совместном использовании записи основной сущности? | — Каскад для активных- Каскад для всех- Без каскадных- Каскад для ответств. |
Отмена общего доступа | Что должно произойти при отмене совместного использования записи основной сущности? | — Каскад для активных- Каскад для всех- Без каскадных- Каскад для ответств. |
Переподчинение | Что должно произойти, когда меняется значение поля поиска для отношения родительского типа в записи основной сущности? Отношение родительского типа — это отношение, использующее Каскад для всех для всех действий. — Каскад для активных- Каскад для всех- Без каскадных- Каскад для ответств. | |
Удаление | Что должно произойти при удалении записи основной сущности? | — Каскад для всех- Удалить связь- Ограничить удаление |
Слияние | Что должно произойти, когда запись основной сущности объединяется с другой записью? | — Каскад для всех- Без каскадных |
Каждое из этих действий можно настроить для управления тем, как действия будут распространяться на записи, связанные с записью основной сущности отношением сущностей 1:N. Параметры поведения представлены в следующей таблице.
Поведение | Описание |
---|---|
Передавать активным | Выполнение действия для всех активных записей связанной сущности. |
Передавать всем | Выполнение действия для всех записей связанной сущности. |
Не передавать никому | Никакие действия не выполняются. |
Удалить ссылку | Удаление значения поля поиска для всех записей связанной сущности. |
Ограничить удаление | Блокировка возможности удаления записи основной сущности, если существуют связанные записи. |
Передавать владельцу | Выполнение действия для всех записей связанной сущности тем же пользователем, что и пользователь записи основной сущности. |
Способ применения этих действий в отношении можно классифицировать и применить с помощью значений поля Тип поведения, описанных в следующей таблице.
Значение поля | Описание |
---|---|
Родительский | Все действия используют поведение Передавать всем. |
Ссылочный | Действия Назначить, Предоставить общий доступ, Отменить общий доступ и Переподчинение используют поведение Не передавать никому. Действие Удалить использует поведение Удалить ссылку. Действие Объединить использует поведение Передавать всем. |
Ссылочный, ограничить удаление | Аналогично значению Ссылочный за исключением того, что действие Удалить использует поведение Ограничить удаление. |
Настраиваемое каскадное | Отдельное поведение можно назначить для каждого действия. Если выбранные значения соответствуют любым другим категориям Тип поведения, значение изменится на значение Тип поведения. |
Связь 1-N — один ко многим
Помним:
у одного клиента — много заказов, нужен список заказов клиента
и тут нюанс — в заказе клиент уже указан:
- зачем создавать и вручную заполнять список заказов..? пахнет костылем
- решение — связь 1-N
Настройка в ELMA:
- Перейдем в клиента
- Добавим свойство заказы
- Укажем тип свойства «Множественная (1-N)» и укажем «ключевую колонку» Клиент из объекта Заказ
дальше интереснее
Посмотрим в базу данных
На диаграмме ничего не поменялось и вот почему:
- база данных знала заранее и нарисовала связь 1-N
- в направлении Заказ -> Клиент соответствие 1-1 , в обратном N-1 ( это пытались сказать разработчики ELMA в начале)
Таблицы выглядят по прежнему:
На этом чудеса не заканчиваются:
- Добавьте еще один заказ клиенту
- Теперь откройте карточку клиента
Что тут произошло:
ELMA не создавала новое поле в таблице а только создала список в объекте клиент который определяется по свойству клиент в поле объекта заказ
Нюансы работы со связями 1-1 и 1-N (также работает из кода)
- Если в заказе указать клиента — он отразится в списке заказов клиента (это известно)
- Если в список заказов клиента добавить заказ — в добавленном заказе изменится клиент (поэтому будьте уверены что нужна связь 1-N а не N-N, читайте о ней дальше)
Связь «Один ко многим»
В типе связей один ко многим одной записи первой таблицы соответствует несколько записей в другой таблице.
Рассмотрим связь учебной базы данных между должностями и сотрудниками, которая относится к рассматриваемому типу.
Записи должностей в таблице «Должность» уникальны, так как нет смысла повторно создавать имеющуюся запись. Записи в таблице «Сотрудники» также уникальны, но несколько различных сотрудников могут находиться на одинаковой должностной позиции.
Символ ключа на конце связи указывает, что таблица, к которой этой конец прилегает, находится на стороне «один» (связанный столбец является первичным ключом), а символ бесконечности находится на стороне «многие» (такой столбец является внешним ключом).
Извлечение данных для связи «многие ко многим» (SELECT)
Возникает логичный вопрос — как же получать данные из базы, используя таблицу связи?
Есть разные варианты для разных ситуаций, которые мы сейчас рассмотрим, но прежде чем проиллюстрировать их, заполните созданные выше таблицы (чтобы вы тоже могли поэкспериментировать с запросами)
Рассмотрим задачу извлечения участников, связанных с данной номинацией — или короче «номинации, и всех, кто подал в неё заявки» (алгоритм извлечения данных в обратную сторону — т.е. «участик и все его номинации» абсолютно аналогичен).
На практике приходится сталкиваться с двумя базовыми ситуациями:
- Извлечение одной сущности номинации и связанных с ней участников
- Извлечение списка сущностей номинаций и связанных с каждой из номинаций участников (т.е. фактически список участников для каждого элемента из списка номинаций).
Извлечение связанных (многие-ко-многим) данных для одной сущности
Пусть у нас известен id () номинации и мы хотим получить сведения об этой номинации и всех участниках в ней.
Во-первых, сделать это можно двумя sql запросами:
- Сначала просто получим кортеж этой номинации:
mysql> SELECT * FROM Nominations WHERE nominationID=4; +--------------+-----------------------------+ | nominationID | title | +--------------+-----------------------------+ | 4 | Лучшее пособие | +--------------+-----------------------------+
- После, опять же зная id номинации (используем в WHERE), достаточно просто сделать LEFT JOIN между таблицей связи и таблицей участников:
SELECT * FROM Tickets_Nominations LEFT JOIN Tickets ON ticket_id = ticketID WHERE Tickets_Nominations.nomination_id = 4;
Получим:
+-----------+---------------+----------+-------------------------- +----------------------------------------------+ | ticket_id | nomination_id | ticketID | name | info | +-----------+---------------+----------+---------------------------+----------------------------------------------+ | 3 | 4 | 3 | Программирование для всех | Некоммерческая образовательная организация | 4 | 4 | 4 | Юный программист | Кружок для детей в д. Простоквашино | 5 | 4 | 5 | IT FOR FREE | Русскоязычное IT-сообщество с уклоном в web | 6 | 4 | 6 | Саша Петров | Студент 2 курса, автор пособия по SQL
— как видим, тут мы получили вообще все колонки (т.к. в запросе указали звездочку *) двух соединённых таблиц (связи и заявок).
Также видим что на номинации с id=4 номинировалось 4-ре участника, кроме их имен видны также и описания.
Все эти данные можно использовать в приложении, после выполнения запроса к БД — например записать, то что нужно в поле, хранящее массив объекта конкретной номинации.
Если вам требуется от массива связанных сущностей только одно поле (напр. имена участников), то решить задачу можно вообще одним sql запросом, используя группировку (GROUP BY) и применимую к группируемым значения колонки функцию конкатенации GROUP_CONCAT():
SELECT Nominations.*, GROUP_CONCAT(Tickets.name SEPARATOR ', ') as participants_names FROM Nominations LEFT JOIN Tickets_Nominations ON Nominations.nominationID = Tickets_Nominations.nomination_id LEFT JOIN Tickets ON Tickets.ticketID = Tickets_Nominations.ticket_id WHERE Tickets_Nominations.nomination_id = 4 GROUP BY Nominations.nominationID;
Получим единственный кортеж:
+--------------+-----------------------------+-----------------------------------------------------------------------------------------------------------------------+ | nominationID | title | participants_names | +--------------+-----------------------------+-----------------------------------------------------------------------------------------------------------------------+ | 4 | Лучшее пособие | Программирование для всех, Юный программист, IT FOR FREE, Саша Петров | +--------------+-----------------------------+-----------------------------------------------------------------------------------------------------------------------+
— здесь мы:
- провели сразу тройной JOIN, как бы поставив таблицу связи между таблицами номинаций и заявок.
- нас интересовали имена участников для 4 номинации — поэтому использовали WHERE Tickets_Nominations.nomination_id = 4
- Группировка (чтобы в итоге получить только одну строку-кортеж) проходила по id номинации (Nominations.nominationID)
- Сконкатенированному полю мы назначили псевдоним (participants_names)
Плюсом такого подхода является то, что в приложении можно использовать готовую строку participants_names, а минусом то, что с этим значением уже нельзя работать как с массивом, явно не преобразовав.