SQL将表的一列分组,从另一列中选择一个值,并连接其余列

时间:2017-10-10 19:53:22

标签: group-by concatenation sql-server-2014

之前我曾问过这个问题(sql to group table of product owners with a column for primary owner and concatenated secondary owners),但它是针对MySQL而且答案使用的是group_concat,这在SQL Server 2014上是不可用的。因为那个问题已得到解答我想我应该为SQL Server 2014问一个新的。

我和他们的主人有一张产品表。每个所有者都在自己的行中,并拥有主要或次要的所有者类型。并非每个产品都有次要所有者。

我需要按产品分组,主要所有者在一列中,所有次要所有者在第二列中连接。如果产品有多个主要所有者,则应选择第一个,其余的则为二级所有者。如果产品没有主要所有者,那么它应该只选择第一个/任何次要所有者。

这是一个输入表:

+---------+------------+----------+
| Product | Owner Type |  Owner   |
+---------+------------+----------+
| a       | primary    | one      |
| a       | secondary  | two      |
| a       | secondary  | three    |
| b       | primary    | four     |
| b       | secondary  | five     |
| c       | primary    | six      |
| d       | secondary  | seven    |
| e       | secondary  | eight    |
| e       | secondary  | nine     |
| f       | primary    | ten      |
| f       | primary    | eleven   |
| f       | secondary  | twelve   |
| f       | secondary  | thirteen |
+---------+------------+----------+

预期结果是:

+---------+---------------+--------------------------+
| Product | Primary Owner |     Secondary Owners     |
+---------+---------------+--------------------------+
| a       | one           | two, three               |
| b       | four          | five                     |
| c       | six           |                          |
| d       | seven         |                          |
| e       | eight         | nine                     |
| f       | ten           | eleven, twelve, thirteen |
+---------+---------------+--------------------------+

如果您发现,产品de没有主要所有者,那么它会选择第一个二级所有者,然后再次将其包含在二级所有者列中。类似于具有两个主要所有者的产品f

我知道如何按产品group使用FOR XML PATH来连接行/字段。在group我知道如何选择Owner Typeprimary的第一个产品。我无法弄清楚的是选择第一个主要所有者并将其从次要所有者列中排除所需的逻辑和/或如果没有主要所有者,则选择第一个次要所有者并将其从次要所有者列中排除。 / p>

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

使用您的示例数据,我使用ROW_NUMBER()和公用表表达式来确定主要和次要所有者。

WITH PrimaryOwners AS
(SELECT Product,Owner AS 'Primary Owner'
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY Product ORDER BY Product) 'RowNumber',
       Product,OwnerType,Owner
        FROM Product) AS tableA
WHERE RowNumber = 1),

SecondaryOwners AS
(SELECT Product,Owner AS 'Secondary Owners'
FROM (SELECT ROW_NUMBER() OVER(PARTITION BY Product ORDER BY Product) 'RowNumber',
       Product,OwnerType,Owner
        FROM Product) AS tableB
WHERE RowNumber <> 1),

SecondaryOwnersGrouped AS
(SELECT DISTINCT Product,
        STUFF((SELECT CAST(', ' AS VARCHAR(MAX)) + [Secondary Owners]
            FROM SecondaryOwners a
            WHERE a.Product = b.Product
            for xml path('')
            ), 1, 1, '') AS 'Secondary Owners'
FROM SecondaryOwners b)

SELECT p.Product,p.[Primary Owner],
       ISNULL(s.[Secondary Owners],'') 'Secondary Owners'
FROM PrimaryOwners p
     LEFT JOIN SecondaryOwnersGrouped s
        ON p.Product = s.Product

结果:

+----------+----------------+------------------------ --+
| Product  | Primary Owner  | Secondary Owners          |
+----------+----------------+---------------------------+
|   a      |    one         |     two, three            |
|   b      |    four        |        five               |
|   c      |    six         |                           |
|   d      |    seven       |                           |
|   e      |    eight       |        nine               |
|   f      |    ten         | eleven, twelve, thirteen  |
+----------+----------------+---------------------------+