我如何选择记录到单行?



我试着写我的sql查询选择多个记录到一行,但它不工作的方式,我期望它目前我的表看起来像这样

tbody> <<tr>1122
person id fruit
1苹果
橙色
香蕉
苹果
橙色
3苹果

您几乎已经完成了,只需要添加max和group by来聚合它。这在当时是一个典型的面试问题。如果我没理解错的话

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;
<表类>person_id苹果橙色香蕉tbody><<tr>1对对对2对对空3对空空

您已经标记了您正在使用的工具(SQL Server Management Studio),可以与不同的DBMS一起使用。由于Microsoft的SQL Server是这个工具中最常用的,我假设您正在使用它。

首先让我们看看你的表。这看起来有点奇怪。它似乎是一种键值表(又名EAV)。每一行都告诉我们一个属性是否为一个人所需要。现在如何在表格中识别一个人呢?列member是唯一的个人ID吗?可能不会,因为那样的话,given_namessurname在表中的位置,会随着每一个元素的加入而改变。为什么当value_needed是"生日"时,同一个ID为1234的人被称为约翰·史密斯,但当value_needed是"移动"时,他被称为"安妮·米勒"?这没有多大意义。所以也许member只是一个标志,不管一个人是否是成员,一个人是由他们的given_namessurname唯一标识的。但话又说回来,为什么同一个人John Smith在value_needed是"Birthday"时是成员,而在value_needed是"Mobile"时却不是成员呢?所以这里有问题。看来你的表格没有标准化。最好有一个人表和一个属性表。

话虽这么说,GROUP BY ___的意思是"我想要每一行结果"。你按个人和他们的value_needed分组。但是您不希望每个人和value_needed都有一个结果行。您希望每个人有一个结果行。因此,按人分组。

然后你SELECT DISTINCT ...。这意味着您想要删除重复的行。但是看看你选择的行。没有重复的。如果你使用GROUP BY,你可以99.99%确定你不需要DISTINCT。(确实存在一些罕见的情况,您自愿按列分组,不要选中所有列然后应用DISTINCT,但这些情况非常罕见,您可能根本不会使用它们。)

现在进入任务:您想要从行转换到列。这被称为枢轴,可以通过PIVOT关键字实现,但更常用的是使用条件聚合。"条件aggregation"意味着您汇总数据(每个人),然后应用一个条件。在标准SQL中:

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

您可以在这里使用MINMAX,这只是出于语法原因(FILTER子句必须引用某个聚合函数)。

在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 Server中使用括号。但更好的做法是,通过在名称中避免使用特殊字符,将它们全部避免。

完整查询:
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;

相关内容

  • 没有找到相关文章

最新更新