在SQL中连接单个列

时间:2011-10-04 21:28:15

标签: tsql sql-server-2008 common-table-expression

我正在使用SSMS 2008并尝试根据不同字段的分组将其中一行连接在一起。我有两列,people_id和address_desc。它们看起来像这样:

address_desc                         people_id
----------                           ------------ 
Murfreesboro, TN  37130              F15D1135-9947-4F66-B778-00E43EC44B9E 
11 Mohawk Rd., Burlington, MA 01803  C561918F-C2E9-4507-BD7C-00FB688D2D6E 
Unknown, UN  00000                   C561918F-C2E9-4507-BD7C-00FB688D2D6E        Jacksonville, NC  28546                  FC7C78CD-8AEA-4C8E-B93D-010BF8E4176D 
Memphis, TN  38133                   8ED8C601-5D35-4EB7-9217-012905D6E9F1 
44 Maverick St., Fitchburg, MA       8ED8C601-5D35-4EB7-9217-012905D6E9F1

现在我想连接address_desc字段/ people_id。所以这里的第一个应该只为地址_desc显示“Murfreesboro,TN 37130”。但第二个人应该只有一行而不是两行,其中“11 Mohawk Rd。,Burlington,MA 01803; Unknown,UN 00000”for address_desc。

我该怎么做?我尝试过使用CTE,但这给了我一个模棱两可的错误:

WITH CTE ( people_id, address_list, address_desc, length  ) 
          AS ( SELECT people_id, CAST( '' AS VARCHAR(8000) ), CAST( '' AS VARCHAR(8000) ), 0
                 FROM dbo.address_view
                GROUP BY people_id
                UNION ALL
               SELECT p.people_id, CAST( address_list + 
                      CASE WHEN length = 0 THEN '' ELSE ', ' END + c.address_desc AS VARCHAR(8000) ), 
                      CAST( c.address_desc AS VARCHAR(8000)), length + 1
                 FROM CTE c
                INNER JOIN dbo.address_view p
                   ON c.people_id = p.people_id
                WHERE p.address_desc > c.address_desc )
SELECT people_id, address_list 
      FROM ( SELECT people_id, address_list, 
                    RANK() OVER ( PARTITION BY people_id ORDER BY length DESC )
               FROM CTE ) D ( people_id, address_list, rank )
     WHERE rank = 1 ;

这是我最初的SQL查询:

SELECT a.address_desc, a.people_id 
FROM dbo.address_view a 
INNER JOIN (SELECT people_id 
FROM dbo.address_view 
GROUP BY people_id 
HAVING COUNT(*) > 1) t 
ON a.people_id = t.people_id 
order by a.people_id

1 个答案:

答案 0 :(得分:2)

您可以像这样使用FOR XML PATH('')

DECLARE @TestData TABLE
(
     address_desc NVARCHAR(100) NOT NULL
    ,people_id UNIQUEIDENTIFIER NOT NULL
);

INSERT  @TestData 
SELECT  'Murfreesboro, TN  37130',              'F15D1135-9947-4F66-B778-00E43EC44B9E'
UNION ALL
SELECT  '11 Mohawk Rd., Burlington, MA 01803',  'C561918F-C2E9-4507-BD7C-00FB688D2D6E'
UNION ALL
SELECT  'Unknown, UN  00000',                   'C561918F-C2E9-4507-BD7C-00FB688D2D6E'
UNION ALL
SELECT  'Memphis, TN  38133',                   '8ED8C601-5D35-4EB7-9217-012905D6E9F1'
UNION ALL
SELECT  '44 Maverick St., Fitchburg, MA',       '8ED8C601-5D35-4EB7-9217-012905D6E9F1';

SELECT  a.people_id,
    (SELECT SUBSTRING(
        (SELECT ';'+b.address_desc
        FROM    @TestData b 
        WHERE   a.people_id = b.people_id
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
        ,2
        ,4000)
    ) GROUP_CONCATENATE
FROM    @TestData a
GROUP BY a.people_id

结果:

people_id                            GROUP_CONCATENATE
------------------------------------ ------------------------------------------------------
F15D1135-9947-4F66-B778-00E43EC44B9E Murfreesboro, TN  37130
C561918F-C2E9-4507-BD7C-00FB688D2D6E 11 Mohawk Rd., Burlington, MA 01803;Unknown, UN  00000
8ED8C601-5D35-4EB7-9217-012905D6E9F1 Memphis, TN  38133;44 Maverick St., Fitchburg, MA