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

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

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