SQL Server 2012 无法正常工作的多个项目的逗号分隔
Comma separated for multiple items not working properly for SQL Sever 2012
我正在使用 SQL Server 2012 (v11.0.5058.0 - X64)。我想为多列执行逗号分隔。由于我的 SQL 服务器版本是 2012 我不能使用 string_agg
或 ListAgg
所以我正在尝试使用 CTE 和 FOR XML PATH
这对我来说是新的。
输出解释:
假设如果一个staff ID
包含多个Cost_Center
那么它应该为各自的Staff_ID
逗号分隔
当前 table:
Staff_No | Name | CostCenter | status |
---------+--------+----------------+----------+
1270 | WASI | 850110 - CPP | Active |
1345 | FAK | 124600 - CPP | Active |
1270 | WASI | 850870 - BKR | Active |
期望的输出:
Staff_No | Name | CostCenter | status |
---------+--------+------------------------------+----------+
1270 | WASI | 850110 - CPP , 850870 - BKR | Active |
1345 | FAK | 124600 - CPP | Active |
我试过这段代码:
WITH CTE_TableName AS
(
SELECT
a.Staff_No, a.Name,
CONVERT(varchar(19), a.COST_CENTER_CODE) + ' - ' + b.COST_CENTER_DESC as CostCenter,
CASE a.Active
WHEN 1 THEN 'Active'
WHEN 2 THEN 'Inactive'
END AS status
FROM
[FAV_VS_STAFF_M] a, [FAV_VS_COST_CENTER_M] b
)
SELECT
t0.Staff_No, t0.Name, t0.status,
STUFF((SELECT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
ORDER BY t2.CostCenter
FOR XML PATH('')), 1, LEN(','), '') AS FieldBs
FROM
CTE_TableName t0
GROUP BY
t0.Staff_No , t0.Name, t0.status
ORDER BY
Staff_No;
我没有得到想要的输出。我哪里出错了?请帮助我
通常,SELECT .. FOR XML ..
的 WHERE
子句应该使子查询依赖于在外部查询的 GROUP BY
子句中列出的完全相同的列。尝试
WITH CTE_TableName AS (
SELECT a.Staff_No , a.Name ,
CONVERT(varchar(19), a.COST_CENTER_CODE) + ' - ' + b.COST_CENTER_DESC as CostCenter,
CASE a.Active WHEN 1 THEN 'Active' WHEN 2 THEN 'Inactive' END AS status
from [FAV_VS_STAFF_M] a, [FAV_VS_COST_CENTER_M] b )
SELECT t0.Staff_No, t0.Name , t0.status
, STUFF((
SELECT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
ORDER BY t2.CostCenter
FOR XML PATH('')), 1, LEN(','), '') AS FieldBs
FROM CTE_TableName t0
GROUP BY t0.Staff_No , t0.Name, t0.status
ORDER BY Staff_No;
如果您只想要不同的值,您需要在内部 SELECT
中使用 DISTINCT
或 GROUP BY
子句。 有许多方法,最简单的是:
STUFF((SELECT DISTINCT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
ORDER BY 1
FOR XML PATH(''), TYPE).value('text()[1]','nvarchar(max)')
, 1, LEN(','), '') AS FieldBs
注意添加 TYPE
和 value('text()[1]','nvarchar(max)')
以确保 XML 正确转义。
如@Serg 所述,您还需要正确关联连接 AND t2.Name = t0.Name AND t2.status = t0.status
给这只猫剥皮的另一种方法:
STUFF((SELECT DISTINCT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
ORDER BY ',' + t2.CostCenter
FOR XML PATH(''), TYPE).value('text()[1]','nvarchar(max)')
, 1, LEN(','), '') AS FieldBs
或者:
STUFF((SELECT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
GROUP BY ',' + t2.CostCenter
ORDER BY ',' + t2.CostCenter
FOR XML PATH(''), TYPE).value('text()[1]','nvarchar(max)')
, 1, LEN(','), '') AS FieldBs
请参阅 this question 了解为什么需要这样指定 ORDER BY
。
我正在使用 SQL Server 2012 (v11.0.5058.0 - X64)。我想为多列执行逗号分隔。由于我的 SQL 服务器版本是 2012 我不能使用 string_agg
或 ListAgg
所以我正在尝试使用 CTE 和 FOR XML PATH
这对我来说是新的。
输出解释:
假设如果一个staff ID
包含多个Cost_Center
那么它应该为各自的Staff_ID
当前 table:
Staff_No | Name | CostCenter | status |
---------+--------+----------------+----------+
1270 | WASI | 850110 - CPP | Active |
1345 | FAK | 124600 - CPP | Active |
1270 | WASI | 850870 - BKR | Active |
期望的输出:
Staff_No | Name | CostCenter | status |
---------+--------+------------------------------+----------+
1270 | WASI | 850110 - CPP , 850870 - BKR | Active |
1345 | FAK | 124600 - CPP | Active |
我试过这段代码:
WITH CTE_TableName AS
(
SELECT
a.Staff_No, a.Name,
CONVERT(varchar(19), a.COST_CENTER_CODE) + ' - ' + b.COST_CENTER_DESC as CostCenter,
CASE a.Active
WHEN 1 THEN 'Active'
WHEN 2 THEN 'Inactive'
END AS status
FROM
[FAV_VS_STAFF_M] a, [FAV_VS_COST_CENTER_M] b
)
SELECT
t0.Staff_No, t0.Name, t0.status,
STUFF((SELECT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
ORDER BY t2.CostCenter
FOR XML PATH('')), 1, LEN(','), '') AS FieldBs
FROM
CTE_TableName t0
GROUP BY
t0.Staff_No , t0.Name, t0.status
ORDER BY
Staff_No;
我没有得到想要的输出。我哪里出错了?请帮助我
通常,SELECT .. FOR XML ..
的 WHERE
子句应该使子查询依赖于在外部查询的 GROUP BY
子句中列出的完全相同的列。尝试
WITH CTE_TableName AS (
SELECT a.Staff_No , a.Name ,
CONVERT(varchar(19), a.COST_CENTER_CODE) + ' - ' + b.COST_CENTER_DESC as CostCenter,
CASE a.Active WHEN 1 THEN 'Active' WHEN 2 THEN 'Inactive' END AS status
from [FAV_VS_STAFF_M] a, [FAV_VS_COST_CENTER_M] b )
SELECT t0.Staff_No, t0.Name , t0.status
, STUFF((
SELECT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
ORDER BY t2.CostCenter
FOR XML PATH('')), 1, LEN(','), '') AS FieldBs
FROM CTE_TableName t0
GROUP BY t0.Staff_No , t0.Name, t0.status
ORDER BY Staff_No;
如果您只想要不同的值,您需要在内部 SELECT
中使用 DISTINCT
或 GROUP BY
子句。 有许多方法,最简单的是:
STUFF((SELECT DISTINCT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
ORDER BY 1
FOR XML PATH(''), TYPE).value('text()[1]','nvarchar(max)')
, 1, LEN(','), '') AS FieldBs
注意添加 TYPE
和 value('text()[1]','nvarchar(max)')
以确保 XML 正确转义。
如@Serg 所述,您还需要正确关联连接 AND t2.Name = t0.Name AND t2.status = t0.status
给这只猫剥皮的另一种方法:
STUFF((SELECT DISTINCT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
ORDER BY ',' + t2.CostCenter
FOR XML PATH(''), TYPE).value('text()[1]','nvarchar(max)')
, 1, LEN(','), '') AS FieldBs
或者:
STUFF((SELECT ',' + t2.CostCenter
FROM CTE_TableName t2
WHERE t2.Staff_No = t0.Staff_No
AND t2.Name = t0.Name AND t2.status = t0.status
GROUP BY ',' + t2.CostCenter
ORDER BY ',' + t2.CostCenter
FOR XML PATH(''), TYPE).value('text()[1]','nvarchar(max)')
, 1, LEN(','), '') AS FieldBs
请参阅 this question 了解为什么需要这样指定 ORDER BY
。