簡體   English   中英

我如何將 select 條記錄合並為一行?

[英]How do I select records into a single row?

我試過將 sql 查詢寫入 select 多條記錄到一行,但它沒有按照我預期的方式工作 目前我的表看起來像這樣

人員編號 水果
1個 蘋果
1個 橘子
1個 香蕉
2個 蘋果
2個 橘子
3個 蘋果

我試過使用 CASE 和 GROUP BY,但它只是提供了額外的記錄,並沒有按照我想要的方式顯示,而是像這樣顯示

SELECT DISTINCT
F.MEMBER
,F.GIVEN_NAMES
,F.SURNAME
--VALUES NEEDED
,CASE WHEN F.VALUE_NEEDED = 'Postal Address' THEN 'Yes' ELSE '' END POSTAL_ADDRESS
,CASE WHEN F.VALUE_NEEDED = 'Birthday' THEN 'Yes' ELSE '' END BIRTHDAY
,CASE WHEN F.VALUE_NEEDED = 'Email Address' THEN 'Yes' ELSE '' END EMAIL_ADDRESS
,CASE WHEN F.VALUE_NEEDED = 'First Name' THEN 'Yes' ELSE '' END FIRST_NAME
,CASE WHEN F.VALUE_NEEDED = 'Surname' THEN 'Yes' ELSE '' END SURNAME
,CASE WHEN F.VALUE_NEEDED = 'Title and Gender' THEN 'Yes' ELSE '' END 'TITLE|GENDER'
,CASE WHEN F.VALUE_NEEDED = 'Mobile' THEN 'Yes' ELSE '' END MOBILE
,CASE WHEN F.VALUE_NEEDED = 'Beneficiary' THEN 'Yes' ELSE '' END BENEFICIARY
FROM #FINAL F
GROUP BY F.MEMBER,F.GIVEN_NAMES
,F.SURNAME,VALUE_NEEDED
ORDER BY F.MEMBER
人員編號 蘋果 橘子 香蕉
1個 是的
1個 是的
1個 是的

如何編寫查詢使其看起來更像這樣?

人員編號 蘋果 橘子 香蕉
1個 是的 是的 是的
2個 是的 是的
3個 是的

你幾乎就在那里,只需要添加最大值和分組依據來聚合它。 這曾經是一個典型的面試問題。 如果我理解正確的話,這樣的事情

with t as 
( 
  select 1 as person_id, 'apple' fruit
  union
  select 1 ,'orange' 
  union
  select 1 ,'banana' 
  union
  select 2 ,'apple' 
  union
  select 2 ,'orange' 
  union
  select 3 ,'apple'
) 
, b as 
(
  select 
    person_id, 
    case when fruit= 'apple' then 'yes' else null end 'apple',
    case when fruit= 'orange' then 'yes' else null end 'orange',
    case when fruit= 'banana' then 'yes' else null end 'banana' 
  from t
)
select
  person_id,
  max(apple) apple,
  max(orange) orange,
  max(banana) banana 
from b 
group by 1;
人員編號 蘋果 橘子 香蕉
1個 是的 是的 是的
2個 是的 是的 NULL
3個 是的 NULL NULL

您已經標記了您正在使用的工具 (SQL Server Management Studio),它可以與不同的 DBMS 一起使用。 由於 Microsoft 的 SQL Server 是該工具中最典型的服務器,因此我假設您正在使用它。

首先讓我們看看你的桌子。 似乎有點奇怪。 它似乎是一種鍵值表(又名 EAV)。 每行告訴我們一個人是否需要一個屬性。 現在如何識別表中的一個人? member是唯一的人員 ID 嗎? 可能不會,因為那樣的話,該表中的given_namessurname會隨着每個條目而改變。 為什么 ID 為 1234 的同一個人在value_needed為“生日”時被稱為 John Smith,而在value_needed為“移動”時被稱為“Anne Miller”? 那沒有多大意義。 所以也許member只是一個標志,一個人是否是一個成員,一個人由他們的given_namessurname唯一標識。 但是話又說回來,為什么當value_needed是“生日”時同一個人約翰·史密斯會成為會員,而當value_needed是“移動”時卻不是會員? 所以這里有些不對勁。 看來你的表沒有規范化。 最好有一張人表和一張屬性表。

話雖如此, GROUP BY ___的意思是“我希望每個 ___ 有一個結果行”。 你按人和他們的value_needed 但是您不希望每個人和value_needed一個結果行。 你想要每人一個結果行。 於是,以人為本。

那么你SELECT DISTINCT... 這意味着您要刪除重復的行。 但是看看你選擇的行。 沒有重復項。 如果您使用GROUP BY ,您可以 99.99% 確定不需要DISTINCT (確實存在您自願按列分組的罕見情況,不要 select 所有這些然后應用DISTINCT ,但這種情況非常罕見,您可能根本不會使用它們。)

現在開始任務:您想要從行到列。 這稱為 pivot,可以使用PIVOT關鍵字來實現,但更常見的是使用條件聚合。 “條件聚合”意味着您聚合您的數據(每人),然后應用條件。 在標准 SQL 中:

SELECT MIN('YES') FILTER (WHERE f.value_needed = 'Postal Address')

您可以在此處使用MINMAX ,並且僅出於語法原因才需要( FILTER子句必須引用某些聚合 function。

在 SQL Server 中沒有FILTER子句,因此您使用CASE表達式代替:

SELECT MIN(CASE WHEN f.value_needed = 'Postal Address' THEN 'YES' END)

如果您想要空字符串''而不是 NULL,請應用COALESCE

SELECT COALESCE(MIN(CASE WHEN f.value_needed = 'Postal Address' THEN 'YES' END), '')

包含特殊字符的列別名,如| 需要報價。 但不是單引號,因為它們表示字符串文字。 在標准 SQL 中使用雙引號,在 SQL 服務器中使用括號。 但更好的是,通過避免名稱中的特殊字符來避免它們。

完整查詢:

SELECT
  person_id,
  MIN(CASE WHEN value_needed = 'Postal Address'   THEN 'yes' end) AS postal_address,
  MIN(CASE WHEN value_needed = 'Birthday'         THEN 'Yes' end) AS birthday,
  MIN(CASE WHEN value_needed = 'Email'            THEN 'Yes' END) AS email_address,
  MIN(CASE WHEN value_needed = 'First Name'       THEN 'Yes' END) AS first_name,
  MIN(CASE WHEN value_needed = 'Surname'          THEN 'Yes' END) AS surname,
  MIN(CASE WHEN value_needed = 'Title and Gender' THEN 'Yes' END) AS title_gender,
  MIN(CASE WHEN value_needed = 'Mobile'           THEN 'Yes' END) AS mobile,
  MIN(CASE WHEN value_needed = 'Beneficiary'      THEN 'Yes' END) AS beneficiary
FROM #FINAL
GROUP BY person_id
ORDER BY person_id;

暫無
暫無

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

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