簡體   English   中英

如何根據關系獲取針對一條記錄的多條記錄?

[英]How to get multiple records against one record based on relation?

我有兩張表 Organization 和 Employee 有一對多的關系,即一個組織可以有多個員工。 現在我想選擇特定組織的所有信息以及該組織所有員工的名字。 最好的方法是什么? 我可以在單個記錄集中獲得所有這些嗎,或者我將不得不根據 no 獲得多行。 員工? 這是我想要的一些圖形演示:

Org_ID      Org_Address    Org_OtherDetails    Employess

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

最初的問題是特定於數據庫的,但也許這是包含更通用答案的好地方。 這是一個常見的問題。 您所描述的概念通常稱為“組連接”。 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

9.0 之前的 PostgreSQL 允許您使用 CREATE AGGREGATE 定義自己的聚合函數。 比 MySQL 稍微多一些工作,但更靈活。 有關更多詳細信息,請參閱此另一篇文章 (當然 PostgreSQL 9.0 及更高版本也有這個選項。)

  • Oracle - 使用LISTAGG 的相同想法。

  • MS SQL Server - 使用STRING_AGG 的相同想法

  • 回退解決方案- 在其他數據庫技術或上面列出的技術的非常非常舊的版本中,您沒有這些組連接功能。 在這種情況下,創建一個將 org_id 作為其輸入並輸出連接的員工姓名的存儲過程。 然后在您的查詢中使用此存儲過程。 此處的其他一些回復包括有關如何編寫此類存儲過程的一些詳細信息。

select 
  o.ID, o.Address, o.OtherDetails,
  MY_CUSTOM_GROUP_CONCAT_PROCEDURE( o.ID ) as Employees
from 
  organization o

由於問題被標記為 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;

在 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() 來做到這一點,但我腦子里想不起來語法

如果您使用 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) 具有不同的成本。

選擇你的毒葯。

最簡潔的答案是不”。

正如其他答案中所述,有特定於供應商的方法可以實現這一結果,但沒有可以在一個查詢中工作的純 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

如果您想查看 ie,則第二種方法適用。 用戶名列表“user1、user2、user3”,但不想自己對字段進行操作...

對於 SQL Server,此項目中的 SQLCLR 聚合受 MSDN 代碼示例的啟發,但它們的性能要好得多,並且允許排序(作為字符串)和備用分隔符(如果需要)。 它們為 SQL Server 提供與 MySQL 的 GROUP_CONCAT幾乎相同的功能。

可以在文檔中找到 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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM