我有一个包含以下数据的表:
Name | UserType | Locations
-----------------------
Mike | A | China
Mike | A | Australia
Mike | B | Mexico
Mike | B | Russia
John | A | Japan
John | A | China
我想要的输出如下:
Name | UserType | Locations
-----------------------
Mike | A | China, Australia
Mike | B | Mexico, Russia
John | A | Japan, China
目前,我可以通过使用' FOR XML PATH'来实现这一目标。像这样:
SELECT Name, UserType, Location =
STUFF((SELECT DISTINCT ', ' + location
from @MyTable b
where b.name = a.name
and b.UserType = a.UserType
FOR XML PATH('')), 1, 2, '')
FROM @MyTable a
@ MyTable是我从中检索数据的表。
我无法使用此查询的原因是因为我正在处理至少约500,000条记录并且需要很长时间才能完成(我必须选择前100行来检查它是否正常工作,因为我认为我的系统已经挂了)。
我一直在寻找,我能找到的所有sqlserver都是这个xml路径的东西。 是否有可能在不使用xml的情况下在sql中实现我想要的东西?或者我应该只获取所有记录并在代码中执行此操作?对于任何想知道这个输出的人都会进入一个excel生成的报告,然后客户端下载。
答案 0 :(得分:0)
首先,写下这样的查询:
SELECT Name, UserType,
STUFF((SELECT DISTINCT ', ' + location
FROM @MyTable b
WHERE b.name = a.name AND b.UserType = a.UserType
FOR XML PATH('')
), 1, 2, ''
) as locations
FROM (SELECT DISTINCT Name, UserType FROM @MyTable) a;
这会将工作量减少到每Name
/ UserTYpe
对仅一个子查询调用。
接下来,您可以在@MyTable(name, UserType, location)
上建立索引。您可以通过将组合声明为唯一键或主键来完成此操作。或者,您可以使用临时表并显式添加索引。
答案 1 :(得分:0)
除非你没有提供真正的表结构和样本数据,否则没有必要探讨“为什么查询很慢”。
i)如果可能的话,你可以改变你的数据库设计。
ii)为什么你一次只能查询5 00,000条记录呢 使用distinct?
试试这个,
declare @t table(Name varchar(50), UserType varchar(50), Locations varchar(50))
insert into @t VALUES
-----------------------
('Mike','A','China' )
,('Mike','A','Australia')
,('Mike','B','Mexico' )
,('Mike','B','Russia' )
,('John','A','Japan' )
,('John','A','China' )
;with CTE as
(
select *
,ROW_NUMBER()over(PARTITION by name,usertype order by name)rn
from @t
)
select name ,usertype
,stuff((select ','+ Locations from cte c1 where c1.name=c.name
and c.usertype=c1.usertype for xml path('')),1,1,'')
Locations
from cte c
where rn=1
答案 2 :(得分:0)
尝试以下查询:
DECLARE @MyTable TABLE ( Name VARCHAR(100), UserType VARCHAR(100),
Locations VARCHAR(100) )
INSERT INTO @MyTable ( Name , UserType , Locations )
SELECT 'Mike','A','China' UNION ALL
SELECT 'Mike','A','Australia' UNION ALL
SELECT 'Mike','B','Mexico' UNION ALL
SELECT 'Mike','B','Russia' UNION ALL
SELECT 'John','A','Japan' UNION ALL
SELECT 'John','A','China'
SELECT Name , UserType ,
STUFF (( SELECT ',' + Locations FROM @MyTable I WHERE I.Name =
O.Name AND I.UserType = O.UserType FOR XML PATH(''))
,1,1,'')
FROM @MyTable O
GROUP BY Name , UserType
在查询下方没有使用XML:
;WITH CTE ( UniqId , _Id , _Name , _UserType , _Locations) AS
(
SELECT 1 , Id , Name , UserType , Locations
FROM @MyTable
UNION ALL
SELECT UniqId + 1 , _Id + 1 , _Name , _UserType , _Locations + ',' +
Locations
FROM CTE
JOIN @MyTable ON _Name = Name AND _UserType = UserType AND _Id < Id
)
SELECT CTE._Name Name, CTE._UserType UserType, CTE._Locations Locations
FROM CTE
JOIN
(
SELECT MAX(UniqId) _UniqId ,_Name , _UserType
FROM CTE
GROUP BY _Name , _UserType
) A ON _UniqId = UniqId AND A._Name = CTE._Name AND A._UserType =
CTE._UserType
答案 3 :(得分:0)
我们可以在CLR Aggregate函数的帮助下不使用'For XML Path'来实现这一目标 试试这个链接clickHere