我有一个简单的表'TABLE_1'
Org Customer Code Ordered Deleted Confirmed
RU Cust_1 A 1000 800 200
RU Cust_2 B 300 0 300
US Cust_3 C 800 100 700
RU Cust_4 B 100 100 0
US Cust_5 C 400 200 200
RU Cust_6 B 500 300 200
现在我需要为这些行转换此表,其中'已删除'<> 0喜欢
Org Code Customers Ordered Confirmed
RU A Cust_1 1000 200
RU B Cust_4, Cust_6 600 200
US C Cust_3, Cust_5 1200 900
我正在使用以下查询和功能
SELECT T1.Org,
T1.Code,
dbo.FUNC(T1.Code, T1.Org) AS 'Customers',
'Ordered' = (SELECT SUM(Ordered) FROM TABLE_1 AS T2 WHERE T2.Customer = T1.Customer AND T2.Code = T1.Code AND T2.Deleted<>0),
'Confirmed' = (SELECT SUM(Confirmed) FROM TABLE_1 AS T3 WHERE T3.Customer = T1.Customer AND T3.Code = T1.Code AND T3.Deleted<>0)
FROM TABLE_1 AS T1
WHERE T1.Deleted <> 0
功能'FUNC':
ALTER FUNCTION [dbo].[FUNC] (@c VARCHAR(MAX), @org VARCHAR(MAX))
RETURNS VARCHAR(MAX) AS BEGIN
DECLARE @p VARCHAR(MAX) ;
SET @p = '' ;
SELECT @p = @p + T1.Customer + ', '
FROM TABLE_1 AS T1
WHERE T1.Code = @c AND T1.Org = @org AND T1.Deleted <> 0
GROUP BY T1.Customer
RETURN SUBSTRING(@p, 1, LEN(@p) - 1)
END
我认为这不是获得结果的最佳方式,特别是如果我有一个大表。 是否有更好的解决方案用于此目的?
修改 表DDL示例
CREATE TABLE [dbo].[TABLE_1](
[Org] [nchar](10) NULL,
[Customer] [nchar](100) NULL,
[Code] [nchar](10) NULL,
[Ordered] [decimal](18,1) NULL,
[Deleted] [decimal](18,1) NULL,
[Confirmed] [decimal](18,1) NULL)
ON [PRIMARY]
答案 0 :(得分:2)
您将面临RBAR&#34;问题&#34;你选择做什么。 然而,您可能会发现使用FOR XML PATH(&#39;&#39;)+ OUTER APPLY而不是您的函数更好。
如果你不了解这些,我会写一段代码来证明这些用法。 但是你可以先提供你的表DDL(+一些行)。
这是:
SELECT
T1.Org
, T1.Code
, ISNULL(STUFF(F.Customers, 1, 2, ''), '') AS Customers
, SUM(T1.Ordered) OVER (PARTITION BY T1.Customer, T1.Code) AS Ordered
, SUM(T1.Confirmed) OVER (PARTITION BY T1.Customer, T1.Code) AS Confirmed
FROM TABLE_1 AS T1
OUTER APPLY (
SELECT
', ' + T2.Customer
FROM TABLE_1 AS T2
WHERE T2.Code = T1.Code
AND T2.Org = T1.Org
AND T2.Deleted <> 0
FOR XML PATH('')
) AS F(Customers)
WHERE T1.Deleted <> 0
答案 1 :(得分:1)
SELECT
Org,
Code,
STUFF(
(SELECT ','+Customer
FROM t WHERE Code=a.Code and Deleted<>0
FOR XML PATH('')) , 1 , 1 , '' ),
SUM(ordered),
SUM(Confirmed)
FROM
t A
where Deleted<>0
group by ORG,code
答案 2 :(得分:1)
什么是最好的可能需要对您的特定数据进行一些测试,但是为了开始,让我们修复您的原始查询,以获得您在问题中按预期编写的正确结果:
SELECT T1.Org,
T1.Code,
dbo.FUNC(T1.Code, T1.Org) AS Customers,
SUM(Ordered) AS Ordered,
SUM(Confirmed) AS Confirmed
FROM TABLE_1 AS T1
WHERE T1.Deleted <> 0
GROUP BY T1.Org, T1.Code
答案 3 :(得分:1)
即使您的客户名称包含XML控件字符,您也可以这样做。
SELECT
t1.[Org],
t1.[Code],
STUFF(
(
SELECT
', ' + c.[Customer]
FROM
[TABLE_1] c
WHERE
c.[Deleted] <> 0
AND
c.[Org] = t1.[Org]
AND
c.[Code] = t1.[Code]
ORDER BY
c.[Customer]
FOR XML PATH (''), TYPE
).value('.', 'varchar(max)'),
1,
2,
'') [Customers],
SUM(t1.[Ordered]),
SUM(t1.[Confirmed])
FROM
[TABLE_1] t1
WHERE
t1.[Deleted] <> 0
GROUP BY
t1.[Org],
t1.[Code];
就性能而言,只做两个查询并担心以后的逗号分隔列表是有意义的。您可以获得相同的信息,但没有字符串聚合的开销,而MSSQL是如此错位而无法实现的。
SELECT
t1.[Org],
t1.[Code],
SUM(t1.[Ordered]),
SUM(t1.[Confirmed])
FROM
[TABLE_1] t1
WHERE
t1.[Deleted] <> 0
GROUP BY
t1.[Org],
t1.[Code];
SELECT
t1.[Org],
t1.[Code],
t1.[Customer]
FROM
[TABLE_1] t1
WHERE
t1.[Deleted] <> 0
ORDER BY
t1.[Org],
t1.[Code],
t1.[Customer];