[英]Combine rows concatenating values
我目前有一張桌子:
id | name | type | type_name
----+-------+------+-----------
101 | John | 1 | cat
101 | John | 2 | dog
253 | Bill | 2 | dog
376 | Rick | 3 | giraffe
376 | Rick | 2 | dog
440 | James | 2 | dog
440 | James | 1 | cat
440 | James | 3 | giraffe
我想構建一個使用表中數據的新視圖。 如果 'name'/'id' 有多個類型,那么下面的 types 列會將它們組合起來:
考慮到只有三種可能的類型,
combinedType:
1 = cat
2 = dog
3 = giraffe
4 = cat and dog
5 = cat and giraffe
6 = dog and giraffe
7 = cat, dog, and giraffe
id | name | combinedTypeID| newTypeName
-----+-------+---------------+------------------
101 | John | 4 | cat and dog
253 | Bill | 2 | dog
376 | Rick | 6 | dog and giraffe
440 | James | 7 | cat, dog, and giraffe
在沒有凌亂的子查詢的情況下,我對此感到很迷茫。
謝謝大家!
如果您可以去掉字符串中的“and”,那么對於 SQL Server 2017 及更高版本,您可以使用 String_agg() 函數,如下所示
Select
ID
, name
, case when count(1) > 1 then sum(type)+1 else sum(type) end as CombinedTypeId
, String_agg(type_name,',') WITHIN GROUP (ORDER BY type) as newTypeName
from MyTable
Group by
ID
, name
order by 1;
這是一個數據庫小提琴鏈接 - https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=f361ab0050d94dce74958ad55a1afc93
如果你不依賴於這些特定的數字和表示,我會建議:
combinedType:
1 = cat
2 = dog
3 = cat, dog
4 = giraffe
5 = cat, giraffe
6 = dog, giraffe
7 = cat, dog, giraffe
通過這種輕微的變化,這些值是相加的。
然后,邏輯非常簡單:
select t.id, t.name, sum(v.val) as type_id,
string_agg(v.type_name, ',') within group (order by v.type_name)
from t join
(values ('cat', 1), ('dog', 2), ('giraffe', 4)
) v(type_name, val)
on t.type_name = v.type_name
group by t.id, t.name;
我認為這個查詢效果很好。 但在最后一種情況“貓、狗和長頸鹿”中,它返回“貓、狗和長頸鹿”。 如果您願意,您可以擁有一個包含組合類型的表並加入第一個 CTE。
with NewTypesResult
as
( select id, name, substring(newTypeName, 1, len(newTypeName) - 4) as newTypeName
from
(
select distinct id, name, (select distinct type_name + ' and '
from myTable
where id = tbl.id
order by 1
for xml path('')) as newTypeName
from dbo.myTable tbl
) as tbl
), FinalResult
as
(
select id, name, newTypeName, case
when newTypeName = 'cat' then 1
when newTypeName like 'dog' then 2
when newTypeName like 'giraffe' then 3
when newTypeName like 'cat and dog' then 4
when newTypeName like 'cat and giraffe' then 5
when newTypeName like 'dog and giraffe' then 6
when newTypeName like 'cat and dog and giraffe' then 7
end as combinedTypeID
from NewTypesResult
)
select id, name, newTypeName, combinedTypeID
from FinalResult
可以通過按 ID 聚合 #Users 表中的字符串並加入 combineType 列來滿足匹配條件。 在combinedType 列的#TypesTable 中,(子字符串)' 和' 被', ' 替換。 在每個 ID 有 3 種類型的情況下,這會導致出現雙逗號,即 ',, '。 所以外部 REPLACE 函數將 ',, ' 改回 ', '。
樣本數據
drop table if exists #Users;
go
create table #Users(
ID int not null,
[name] nvarchar(50),
[type] int,
[type_name] nvarchar(50));
go
insert #Users(ID, [name], [type], [type_name]) values
(101, 'John', 1, 'cat'),
(101, 'John', 2, 'dog'),
(253, 'Bill', 2, 'dog'),
(376, 'Rick', 3, 'giraffe'),
(376, 'Rick', 2, 'dog'),
(440, 'James', 2, 'dog'),
(440, 'James', 1, 'cat'),
(440, 'James', 3, 'giraffe');
drop table if exists #TypesTable;
go
create table #TypesTable(
[type] int primary key,
combinedType nvarchar(100));
go
insert #TypesTable([type], combinedType) values
(1, 'cat'),
(2, 'dog'),
(3, 'giraffe'),
(4, 'cat and dog'),
(5, 'cat and giraffe'),
(6, 'dog and giraffe'),
(7, 'cat, dog, and giraffe');
詢問
with
types_cte(ID, [Name], combinedType) as (
select ID, [Name], string_agg([type_name], ', ')
within group (order by [type_name])
from #Users
group by ID, [Name])
select tc.id, tc.[name], t.[type] combinedTypeID, t.combinedType
from types_cte tc
join #TypesTable t on tc.combinedType=replace(replace(t.combinedType, ' and ', ', '), ',, ', ', ')
order by 1;
輸出
id name combinedTypeID combinedType
101 John 4 cat and dog
253 Bill 2 dog
376 Rick 6 dog and giraffe
440 James 7 cat, dog, and giraffe
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.