[英]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_names
和surname
會隨着每個條目而改變。 為什么 ID 為 1234 的同一個人在value_needed
為“生日”時被稱為 John Smith,而在value_needed
為“移動”時被稱為“Anne Miller”? 那沒有多大意義。 所以也許member
只是一個標志,一個人是否是一個成員,一個人由他們的given_names
和surname
唯一標識。 但是話又說回來,為什么當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')
您可以在此處使用MIN
或MAX
,並且僅出於語法原因才需要( 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.