如何基于关系从一条记录获取多条记录?

时间:2020-03-06 14:26:12  来源:igfitidea点击:

我有两个表Organization和Employee具有一对多关系,即一个组织可以有多个员工。现在,我要选择特定组织的所有信息以及该组织所有雇员的名字。最好的方法是什么?我可以在单个记录集中获取所有这些信息,还是必须基于否获得多个行。员工?这是我想要的图形演示:

Org_ID      Org_Address    Org_OtherDetails    Employess

1           132A B Road    List of details     Emp1, Emp2, Emp3.....

解决方案

如果我们使用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行)。那是有代价的。
如果我们执行两个查询。 (单位和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()来完成此操作,但是却记不清语法的含义

最简洁的答案是不"。

正如在其他答案中所指出的那样,有一些特定于供应商的方法可以实现此结果,但是没有纯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/zh-CN/group-by-functions.html#function_group-concat

如果我们想查看ie,则可以使用第二种方法。用户名" 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(expression,delimiter)。这是元素之间的"逗号空间":
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
  • 其他DBMS技术-最有可能使用存储过程路由。也许其他人可以使用更多技术特定的答案来更新此答案。