简体   繁体   English

我如何将 select 条记录合并为一行?

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

I've tried writing my sql query to select multiple records on to one row but it isn't working the way I expected it to Currently my table looks something like this我试过将 sql 查询写入 select 多条记录到一行,但它没有按照我预期的方式工作 目前我的表看起来像这样

person id人员编号 fruit水果
1 1个 apple苹果
1 1个 orange橘子
1 1个 banana香蕉
2 2个 apple苹果
2 2个 orange橘子
3 3个 apple苹果

I've tried using CASE and GROUP BY but it just gave extra records and didn't display the way I wanted it to and is displaying like this我试过使用 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
person id人员编号 apple苹果 orange橘子 banana香蕉
1 1个 yes是的
1 1个 yes是的
1 1个 yes是的

How do I write the query so it looks more like this?如何编写查询使其看起来更像这样?

person id人员编号 apple苹果 orange橘子 banana香蕉
1 1个 yes是的 yes是的 yes是的
2 2个 yes是的 yes是的
3 3个 yes是的

You are almost there, just needed to add the max and group by to aggregate it.你几乎就在那里,只需要添加最大值和分组依据来聚合它。 This used to be a typical interview question back then.这曾经是一个典型的面试问题。 Some thing like this if I understood correctly如果我理解正确的话,这样的事情

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人员编号 apple苹果 orange橘子 banana香蕉
1 1个 yes是的 yes是的 yes是的
2 2个 yes是的 yes是的 NULL NULL
3 3个 yes是的 NULL NULL NULL NULL

You have tagged the tool that you are using (SQL Server Management Studio) which can be used with different DBMS.您已经标记了您正在使用的工具 (SQL Server Management Studio),它可以与不同的 DBMS 一起使用。 As Microsoft's SQL Server is the most typical used in this tool, I assume your are using that.由于 Microsoft 的 SQL Server 是该工具中最典型的服务器,因此我假设您正在使用它。

First let's look at your table.首先让我们看看你的桌子。 It seems a bit weird.似乎有点奇怪。 It seems to be a kind of key-value table (aka EAV).它似乎是一种键值表(又名 EAV)。 Each row tells us for an attribute whether it is needed for a person.每行告诉我们一个人是否需要一个属性。 Now how to identify a person in the table?现在如何识别表中的一个人? Is the column member a unique person ID?member是唯一的人员 ID 吗? Probably not, because then, what would be given_names and surname be for in that table, that can change with every entry.可能不会,因为那样的话,该表中的given_namessurname会随着每个条目而改变。 Why would the same person with the ID 1234 be called John Smith when the value_needed is 'Birthday', but be called 'Anne Miller' when value_needed is 'Mobile'?为什么 ID 为 1234 的同一个人在value_needed为“生日”时被称为 John Smith,而在value_needed为“移动”时被称为“Anne Miller”? That wouldn't make much sense.那没有多大意义。 So maybe member is just a flag, whether a person is a member or not, and a person is uniquely identified by their given_names and surname .所以也许member只是一个标志,一个人是否是一个成员,一个人由他们的given_namessurname唯一标识。 But then again, why would the same person John Smith be a member when value_needed is 'Birthday', but not a member when value_needed is 'Mobile'?但是话又说回来,为什么当value_needed是“生日”时同一个人约翰·史密斯会成为会员,而当value_needed是“移动”时却不是会员? So something is amiss here.所以这里有些不对劲。 It seems your table is not normalized.看来你的表没有规范化。 Better have one person table and one table for the attributes.最好有一张人表和一张属性表。

That being said, GROUP BY ___ means "I want one result row per ___".话虽如此, GROUP BY ___的意思是“我希望每个 ___ 有一个结果行”。 You group by the person and their value_needed .你按人和他们的value_needed But you don't want one result row per person and value_needed .但是您不希望每个人和value_needed一个结果行。 You want one resut row per person.你想要每人一个结果行。 Hence, group by person.于是,以人为本。

Then you SELECT DISTINCT... .那么你SELECT DISTINCT... This means you want to remove duplicate rows.这意味着您要删除重复的行。 But look at the rows you are selecting.但是看看你选择的行。 There are no duplicates.没有重复项。 If you use GROUP BY , you can be 99.99% sure you don't need DISTINCT .如果您使用GROUP BY ,您可以 99.99% 确定不需要DISTINCT (There do exist rare situations where you voluntarily group by columns, don't select all of them and then apply DISTINCT , but these are so rare that you probably won't ever use them at all.) (确实存在您自愿按列分组的罕见情况,不要 select 所有这些然后应用DISTINCT ,但这种情况非常罕见,您可能根本不会使用它们。)

Now to the task: You want to get from rows to columns.现在开始任务:您想要从行到列。 This is called pivot and can be achieved with the PIVOT keyword, but it is more common to use conditional aggregation.这称为 pivot,可以使用PIVOT关键字来实现,但更常见的是使用条件聚合。 "Conditional aggregation" means that you aggregate your data (per person) and then apply a condition. “条件聚合”意味着您聚合您的数据(每人),然后应用条件。 In standard SQL:在标准 SQL 中:

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

You can use MIN or MAX here, and it is only required for syntax reasons (the FILTER clause must refer to some aggregation function.您可以在此处使用MINMAX ,并且仅出于语法原因才需要( FILTER子句必须引用某些聚合 function。

In SQL Server there is no FILTER clause, so you use a CASE expression instead:在 SQL Server 中没有FILTER子句,因此您使用CASE表达式代替:

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

If you want the empty string '' instead of NULL, apply COALESCE :如果您想要空字符串''而不是 NULL,请应用COALESCE

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

Columns aliases containing special characters like |包含特殊字符的列别名,如| require quoting.需要报价。 But not single quotes, as these denote string literals.但不是单引号,因为它们表示字符串文字。 In standard SQL use double quotes, in SQL Server use brackets.在标准 SQL 中使用双引号,在 SQL 服务器中使用括号。 But better, just avoid them alltogether, by avoiding special characters in names.但更好的是,通过避免名称中的特殊字符来避免它们。

The complete query:完整查询:

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