[英]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.