这是我的询问:
SELECT
wp.WorkplanID,
STUFF((SELECT ', ' + ISNULL(ul.FirstName + ' ', '') + ISNULL(ul.LastName, '')
FROM UserLogin ul
INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
WHERE wpv.WorkPlanID = wp.WorkPlanID
FOR XML PATH('')), 1, 2, '') AS VendorName,
STUFF((SELECT ', ' + v.PrimaryPhone
FROM UserLogin ul
INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
WHERE wpv.WorkPlanID = wp.WorkPlanID
FOR XML PATH('')), 1, 2, '') AS PrimaryPhone,
STUFF((SELECT ', ' + ul.Email
FROM UserLogin ul
INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
WHERE wpv.WorkPlanID = wp.WorkPlanID
FOR XML PATH('')), 1, 2, '') AS Email
FROM WorkPlan wp
获取数据需要 5 秒,但我想让它更快。
您对三列使用了相同的查询。您可以使用公共表表达式一次连接表并在查询中使用此引用,如下所示:
WITH CTE_WorkPlanVendors AS (
SELECT wpv.WorkPlanID AS VendorWorkPlanID, ul.FirstName, ul.LastName, v.PrimaryPhone, ul.Email
FROM UserLogin ul
INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
)
SELECT wp.WorkplanID,
STUFF((SELECT ', ' + ISNULL(FirstName + ' ', '') + ISNULL(LastName, '')
FROM CTE_WorkPlanVendors cte
WHERE cte.VendorWorkPlanID = wp.WorkPlanID
FOR XML PATH('')), 1, 2, '') AS VendorName,
STUFF((SELECT ', ' + PrimaryPhone
FROM CTE_WorkPlanVendors cte
WHERE cte.VendorWorkPlanID = wp.WorkPlanID
FOR XML PATH('')), 1, 2, '') AS PrimaryPhone,
STUFF((SELECT ', ' + Email
FROM CTE_WorkPlanVendors cte
WHERE cte.VendorWorkPlanID = wp.WorkPlanID
FOR XML PATH('')), 1, 2, '') AS Email
FROM WorkPlan wp;
现有答案没有帮助,因为它们都多次查询基表。
您可以使用以下解决方案来查询一次基表并将其聚合起来:
APPLY
中,使用 FOR XML PATH('row')
将整个数据集聚合到一个 XML 中。添加逗号。SELECT
中,查询每一列如下:
.query('row/TheColumn/text()')
这将为您提供该名称的所有文本元素。.value('text()[1]', 'nvarchar(max)')
这不会转义任何 XML 编码。STUFF
去掉前导逗号。SELECT
wp.WorkplanID,
STUFF(x.x.query('row/Name/text()' ).value('text()[1]', 'nvarchar(max)'), 1, 2, '') AS VendorName,
STUFF(x.x.query('row/PrimaryPhone/text()').value('text()[1]', 'nvarchar(max)'), 1, 2, '') AS PrimaryPhone,
STUFF(x.x.query('row/Email/text()' ).value('text()[1]', 'nvarchar(max)'), 1, 2, '') AS Email
FROM (
SELECT wp.WorkplanID
FROM WorkPlan wp
GROUP BY wp.WorkplanID
) wp
CROSS APPLY (
SELECT
',' + ISNULL(FirstName + ' ', '') + ISNULL(LastName, '') AS Name
',' + v.PrimaryPhone AS PrimaryPhone,
',' + ul.Email AS Email
FROM UserLogin ul
INNER JOIN Vendors v ON ul.UserLoginID = v.UserLoginID
INNER JOIN dbo.WorkPlanVendors wpv ON wpv.VendorID = CAST(v.VendorID AS INT)
WHERE wpv.WorkPlanID = wp.WorkPlanID
FOR XML PATH('row')
) x(x);
显然,在较新版本的 SQL Server 中,您不需要任何这些,您只需使用
STRING_AGG
。
;
WITH CTE
AS (
SELECT wp.WorkplanID
,ISNULL(ul.FirstName + ' ', '') + ISNULL(ul.LastName, '') AS FULLNAME
,v.PrimaryPhone
,ul.Email
FROM WorkPlan wp
INNER JOIN WorkPlanVendors wpv ON wpv.WorkPlanID = wp.WorkPlanID
INNER JOIN Vendors v ON wpv.VendorID = CAST(v.VendorID AS INT)
INNER JOIN UserLogin ul ON ul.UserLoginID = v.UserLoginID
)
SELECT C.WorkplanID
,STUFF((
SELECT ', ' + FULLNAME
FROM CTE CFN
WHERE C.WorkPlanID = CFN.WorkPlanID
FOR XML PATH('')
), 1, 2, '') AS FULLNAME
,STUFF((
SELECT ', ' + PrimaryPhone
FROM CTE CPP
WHERE C.WorkPlanID = CPP.WorkPlanID
FOR XML PATH('')
), 1, 2, '') AS PrimaryPhone
,STUFF((
SELECT ', ' + Email
FROM CTE CEM
WHERE C.WorkPlanID = CEM.WorkPlanID
FOR XML PATH('')
), 1, 2, '') AS Email
FROM CTE C