需要解释Stuff函数和For XML Path如何在此代码中工作

时间:2017-02-17 20:44:45

标签: sql sql-server tsql

我从离开公司的人那里继承了一个SQL脚本,我不确定它在做什么。

第一部分选择用户名及其位置,并将数据放入临时表#Roster:

    LastName  FirstName  Location
    Smith     John       Tampa Hospital
    Kennedy   Tom        Maine Hospital
    Smith     John       Orlando Hospital

第二部分看起来像这样

SELECT DISTINCT lastname, firstname,
STUFF((SELECT DISTINCT ',' + r1.location
from #Roster r2
where r1.lastname = r2.lastname
and r1.firstname = r2.firstname
FOR XML PATH('')), 1, 1, '')
FROM #Roster as r1

当我查看使用STUFF函数的Select中的数据集时,我看不到代码第一部分的任何差异,除了现在按名称和位置排序数据。

有人能说出为什么需要使用STUFF和FOR XML PATH()的脚本的第二部分吗?

感谢。

    LastName    FirstName    Location
    Kennedy     Tom          Maine Hospital
    Smith       John         Orlando Hospital
    Smith       John         Tampa Hospital

2 个答案:

答案 0 :(得分:0)

不确定为什么DISTINCT在此查询中不是一次而是两次。此类查询的要点是为组生成相关值的分隔列表。在您的情况下,它将是每个人的位置。但是,不同的和其他一些事情使得这不能按预期工作。

在这里猜测,但我认为您的查询应该是这样的。

SELECT lastname
    , firstname
    , STUFF((SELECT ',' + location
    from #Roster r2
    where r1.lastname = r2.lastname
        and r1.firstname = r2.firstname
    FOR XML PATH('')), 1, 1, '')
FROM #Roster as r1
group by r1.lastname
    , r1.firstname

答案 1 :(得分:0)

r1.location更改为r2.location位置将提供您期望的字符串连接。

我更改了别名,以免使用问题中代码之类的数字。

create table t (LastName varchar(32), FirstName varchar(32), Location varchar(32))
insert into t values 
 ('Smith','John','Tampa Hospital')
,('Kennedy','Tom','Maine Hospital')
,('Smith','John','Orlando Hospital')

select distinct lastname, firstname
, Location= stuff((select distinct ',' + i.location
    from t as i
    where t.lastname = i.lastname
      and t.firstname = i.firstname
    for xml path('')), 1, 1, '')
from t

返回:

+----------+-----------+---------------------------------+
| lastname | firstname |            Location             |
+----------+-----------+---------------------------------+
| Kennedy  | Tom       | Maine Hospital                  |
| Smith    | John      | Orlando Hospital,Tampa Hospital |
+----------+-----------+---------------------------------+

但问题中的代码引用了location的子查询中的外部表:

select distinct lastname, firstname
, Location= stuff((select distinct ',' + t.location
    from t as i
    where t.lastname = i.lastname
      and t.firstname = i.firstname
    for xml path('')), 1, 1, '')
from t

返回:

+----------+-----------+------------------+
| lastname | firstname |     Location     |
+----------+-----------+------------------+
| Kennedy  | Tom       | Maine Hospital   |
| Smith    | John      | Orlando Hospital |
| Smith    | John      | Tampa Hospital   |
+----------+-----------+------------------+