Как получить несколько записей против одной записи на основе отношения?

У меня есть две таблицы, Организация и Сотрудник, имеющие отношение один ко многим, то есть в одной организации может быть несколько сотрудников. Теперь я хочу выбрать всю информацию о конкретной организации, а также имена всех сотрудников этой организации. Как лучше всего это сделать? Могу ли я получить все это в одном наборе записей, или мне придется получить несколько строк в зависимости от номера. сотрудников? Вот небольшая графическая демонстрация того, что я хочу:

Org_ID      Org_Address    Org_OtherDetails    Employess

1           132A B Road    List of details     Emp1, Emp2, Emp3.....
Освоение архитектуры микросервисов с 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
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
9
0
29 589
9

Ответы 9

Если вы используете Oracle, вы можете создать функцию PL / SQL, которую вы можете использовать в своем запросе, которая принимает в качестве входных данных идентификатор organization_id и возвращает имена всех сотрудников, принадлежащих этой организации, в виде строки. Например:-

select
   o.org_id,
   o.org_address,
   o.org_otherdetails,
   org_employees( o.org_id ) as org_employees
from
   organization o

Все это зависит. Если вы выполните соединение, вы получите все данные организации в каждой строке. (По 1 строке на сотрудника). Это имеет свою цену. Если вы сделаете два запроса. (Org и Emp), у которых другая стоимость.

Выбрать свой яд.

в MS SQL вы можете:

create function dbo.table2list (@input int)
returns varchar(8000)
as
BEGIN
declare @putout varchar(8000)
set @putout = ''
select @putout = @putout + ', ' + <employeename>
from <employeetable>
where <orgid> = @input
return @putout
end

затем сделайте:

select * from org, dbo.table2list(orgid)
from <organisationtable>

Я думаю, вы можете сделать это и с помощью COALESCE (), но не могу вспомнить синтаксис из головы

Конечно, как только общее количество имен всех ваших сотрудников, включая запятые и пробелы, достигнет 8000 - у вас проблема!

Valerion 19.09.2008 18:54

Короткий ответ - нет".

Как отмечалось в других ответах, существуют способы достижения этого результата, зависящие от поставщика, но нет чистого решения SQL, которое работает с одним запросом.

Извини за это :(

Предположительно, вам подойдет одно из решений конкретного производителя?

Вот что вы можете сделать, у вас есть 2 варианта:

select *
FROM
  users u
  LEFT JOIN organizations o ON (u.idorg = o.id);

Таким образом вы получите дополнительные данные по каждой строке - полную информацию об организации, которая вам действительно не нужна.

Или вы можете сделать:

select o.*, group_concat(u.name)
FROM
  users u
  LEFT JOIN organizations o ON (u.idorg = o.id)
GROUP BY
  o.id

http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

Второй подход применим, если вы хотите увидеть, т.е. список имен пользователей "user1, user2, user3", но не хотят работать с самими полями ...

Поскольку вопрос помечен как MySQL, вы сможете использовать решение для MySQL, а именно GROUP_CONCAT. Например,

select Org_ID, Org_Address, Org_OtherDetails,
       GROUP_CONCAT(employees) as Employees
from  employees a, organization b
where a.org_id=b.org_id
group by b.org_id;

Первоначальный вопрос касался конкретной базы данных, но, возможно, это хорошее место для включения более общего ответа. Обычный вопрос. Концепция, которую вы описываете, часто называют «групповой конкатенацией». В SQL-92 или SQL-99 нет стандартного решения. Так что вам понадобится решение для конкретного производителя.

  • MySQL - Наверное, самое простое решение. Используйте встроенную функцию GROUP_CONCAT. В вашем примере вам нужно что-то вроде этого:
select 
  o.ID, o.Address, o.OtherDetails,
  GROUP_CONCAT( concat(e.firstname, ' ', e.lastname) ) as Employees
from 
  employees e 
  inner join organization o on o.org_id=e.org_id
group by o.org_id
  • PostgreSQL - Обновлено: PostgreSQL 9.0 теперь так же прост, когда встроен string_agg (выражение, разделитель). Вот это с пробелом между элементами:
select 
  o.ID, o.Address, o.OtherDetails,
  STRING_AGG( (e.firstname || ' ' || e.lastname), ', ' ) as Employees
from 
  employees e 
  inner join organization o on o.org_id=e.org_id
group by o.org_id

PostgreSQL до 9.0 позволяет вам определять свои собственные агрегатные функции с помощью CREATE AGGREGATE. Немного больше работы, чем MySQL, но гораздо более гибкий. См. Этот другой пост для более подробной информации. (Конечно, PostgreSQL 9.0 и более поздние версии также имеют эту опцию.)

  • Oracle и MS SQL Server - Создайте хранимую процедуру, которая принимает org_id в качестве входных данных и выводит объединенные имена сотрудников. Затем используйте эту хранимую процедуру в своем запросе. Некоторые из других ответов здесь содержат некоторые подробности о том, как писать подобные хранимые процедуры.
select 
  o.ID, o.Address, o.OtherDetails,
  MY_CUSTOM_GROUP_CONCAT_PROCEDURE( o.ID ) as Employees
from 
  organization o
  • Другие технологии СУБД - наиболее вероятен маршрут хранимой процедуры. Возможно, другие смогут дополнить этот ответ более конкретными ответами на технологии.

Для SQL Server агрегаты SQLCLR в этом проекте вдохновлены примером кода MSDN, однако они работают намного лучше и позволяют при необходимости сортировать (в виде строк) и использовать альтернативные разделители. Они предлагают функциональность, эквивалентную почти MySQL GROUP_CONCAT для SQL Server.

Полное сравнение преимуществ / недостатков агрегатов CLR и решения FOR XML можно найти в документации:

http://groupconcat.codeplex.com

Для SQL Server 2017 и Azure SQL теперь есть функция STRING_AGG (Transact-SQL), чтобы это было на одном уровне с MySQL:

https://docs.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver15.

SELECT attribute1, STRING_AGG (attribute2, '|') AS Attribute2
FROM  table
GROUP BY attribute

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