簡體   English   中英

合並行連接值

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM