Как получить несколько записей по одной записи на основе отношения?
У меня есть две таблицы: Организация и Сотрудник имеют отношение один к большому числу. Одна организация может иметь несколько сотрудников. Теперь я хочу выбрать всю информацию конкретной организации плюс имя всех сотрудников этой организации. Каков наилучший способ сделать это? Могу ли я получить все это в одном наборе записей, или мне придется получить несколько строк на основе нет. из сотрудников? Вот небольшая графическая демонстрация того, что я хочу:
Org_ID Org_Address Org_OtherDetails Employess
1 132A B Road List of details Emp1, Emp2, Emp3.....
Ответы
Ответ 1
Первоначальный вопрос был специфичным для базы данных, но, возможно, это хорошее место, чтобы включить более общий ответ. Это общий вопрос. Концепцию, которую вы описываете, часто называют "Групповое сцепление". В 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
- Другие технологии СУБД. Наиболее вероятен маршрут хранимой процедуры. Возможно, другие могут обновить этот ответ с помощью более конкретных технологий.
Ответ 2
Поскольку вопрос помечен как 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;
Ответ 3
в 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
то do:
select * from org, dbo.table2list(orgid)
from <organisationtable>
Я думаю, вы можете сделать это также с COALESCE(), но не можете вспомнить синтаксис с моей головы
Ответ 4
Если вы используете Oracle, вы можете создать PL/SQL-функцию, которую вы можете использовать в своем запросе, который принимает имя организации_вход, и возвращает имя всех сотрудников, принадлежащих к этой организации, в виде строки. Например: -
select
o.org_id,
o.org_address,
o.org_otherdetails,
org_employees( o.org_id ) as org_employees
from
organization o
Ответ 5
Все зависит.
Если вы выполните соединение, вы получаете все данные организации в каждой строке. (1 строка на одного сотрудника). У этого есть стоимость.
Если вы выполните два запроса. (Org и Emp), которые имеют разную стоимость.
Выберите свой яд.
Ответ 6
Короткий ответ - "нет".
Как отмечалось в других ответах, существуют конкретные способы достижения этого результата, но нет чистого решения SQL, которое работает в одном запросе.
извините за это: (
Предположительно, для вас будет работать один из решений для конкретного поставщика?
Ответ 7
Здесь, что вы можете сделать, у вас есть 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
Второй подход применим, если вы хотите увидеть ie. список имен пользователей "user1, user2, user3", но не хотят работать с самими полями...
Ответ 8
Для SQL Server SQLCLR агрегаты в этом проекте вдохновлены примером кода MSDN, однако они работают намного лучше и позволяют при необходимости сортировать (как строки) и альтернативные разделители. Они предлагают почти эквивалентную функциональность MySQL GROUP_CONCAT для SQL Server.
Полное сравнение преимуществ/недостатков агрегатов CLR и решения FOR XML можно найти в документации:
http://groupconcat.codeplex.com