SQL Server 2000中:思路进行串联聚合子查询
-
18-09-2019 - |
题
我有希望,e.g。
,返回行的查询QuestionID QuestionTitle UpVotes DownVotes
========== ============= ======= =========
2142075 Win32: Cre... 0 0
2232727 Win32: How... 2 0
1870139 Wondows Ae... 12 0
现在我想有一个的列强>返回,包含以逗号分隔的“作者”(例如原始的海报和编辑的)列表。 e.g:
QuestionID QuestionTitle UpVotes DownVotes Authors
========== ============= ======= ========= ==========
2142075 Win32: Cre... 0 0 Ian Boyd
2232727 Win32: How... 2 0 Ian Boyd, roygbiv
1870139 Wondows Ae... 12 0 Ian Boyd, Aaron Klotz, Jason Diller, danbystrom
结果
伪造它
SQL Server 2000中没有一个CONCAT(AuthorName, ', ')
聚合操作,我一直在装病 - 为TOP 1
笔者进行简单的子查询,笔者计数
QuestionID QuestionTitle UpVotes DownVotes FirstAuthor AuthorCount
========== ============= ======= ========= =========== ===========
2142075 Win32: Cre... 0 0 Ian Boyd 1
2232727 Win32: How... 2 0 Ian Boyd 2
1870139 Wondows Ae... 12 0 Ian Boyd 3
如果有一个以上的作者,然后我显示该用户的省略号(“...”),以指示存在多于一个。例如用户将看到:
QuestionID QuestionTitle UpVotes DownVotes Authors
========== ============= ======= ========= ==========
2142075 Win32: Cre... 0 0 Ian Boyd
2232727 Win32: How... 2 0 Ian Boyd, …
1870139 Wondows Ae... 12 0 Ian Boyd, …
和行之有效足够,因为通常一个的问题未编辑 - 这意味着我完全支撑所述99%的情况下,和1%的情况下,只有一半<击> -assed 击>以及
结果
螺纹重新查询
作为一个更复杂的,并且容易出错的溶液,想到迭代所显示的列表的,和纺纱了线程池工作线程对每个“问题”中的列表中,执行一个对数据库查询来获取作者列表,然后聚集在内存中的列表。这意味着列表第一填补了(本机)应用程序。然后,我事后发出几千个人查询。
但是,这将是可怕,窘况,非常慢。且不说缺陷困扰的,因为这将是线程的工作。
结果
耶
亚当技工说一清二楚的:
不串接行到分隔 字符串在SQL Server中。做客户端 侧。
告诉我怎么了,我会做到这一点。
结果
/哭
谁能想到一个更好的解决办法,就是以最快的速度(说...一个数量级内)比我原来的“TOP 1加省略号”的解决方案?
例如,有一种方法来返回一个结果集,其中到达行具有相关联的结果设置?因此,对于每一个“主”行,我能得到在包含列表中的“细节”的结果集。
结果
代码最佳答案
凯德的连结亚当Machanic的解决方案我最喜欢的。用户定义的函数,这似乎通过魔术操作:
CREATE FUNCTION dbo.ConcatAuthors(@QuestionID int)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE @Output VARCHAR(8000)
SET @Output = ''
SELECT @Output = CASE @Output
WHEN '' THEN AuthorName
ELSE @Output + ', ' + AuthorName
END
FROM (
SELECT QuestionID, AuthorName, QuestionDate AS AuthorDate FROM Questions
UNION
SELECT QuestionID, EditorName, EditDate FROM QuestionEdits
) dt
WHERE dt.QuestionID = @QuestionID
ORDER BY AuthorDate
RETURN @Output
END
使用的T-SQL用法:
SELECT QuestionID, QuestionTitle, UpVotes, DownVotes, dbo.ConcatAuthors(AuthorID)
FROM Questions
解决方案
看一看这些文章:
http://dataeducation.com/rowset-string-级联-其中-方法-是最佳/
HTTP: //www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/ (见菲尔因子的十字架在回应加入的解决方案 - 这将在SQL工作服务器2000)
在SQL Server 2005中很明显,FOR XML技巧是最简单,最灵活,通常最高效的。
据,返回行集的每一行,如果你仍然想这样做,出于某种原因,你可以做,在存储过程,但客户端将需要消耗中的所有行第一行集,然后去下一行集,并在第一行集中的第一行联营等你的SP需要打开在同一组,它返回的第一行集光标并按顺序运行多个选择来产生所有的子行集。这是一个技术,我已经做了,但只有其中全部实际需要的数据(例如,在一个完全填充的树视图)。
和不管别人说什么,做客户端的往往是带宽的一个非常大的浪费,因为返回的所有行,做循环,并在客户端的突破意味着相同的列的数量庞大的在被转移每行的开始正好在该行的末尾得到改变柱。
只要你做到这一点,它应该是一个明智的决定根据您使用情况。
其他提示
我试图方法3在该溶液中,一个贴在这里,ActiveX脚本和UDF功能。
对我来说,最有效的脚本(速度明智)为运行多个查询到additioanl数据到达的concat bizzarely Axtive-X脚本。
UDF花了22分钟的平均转换,子查询方法(在这里发布)前后花了五楼,ActiveX脚本了4m30,这让我烦恼,因为这是我希望沟脚本。我得看看我是否能在其他地方烫出了几个更高的效率。
我认为额外的30年代所使用tempdb的用来存储数据,因为我的脚本需要通过一个订单。
应该指出的是,我concatanating文本大量的数据。
您也可以看看这个脚本。它基本上是交叉连接的是凯德空肠Roux也是他在文章中提到的方法。
在上面的方法看起来很干净:你必须首先做一个视图,其次建立基于视图中的值的声明。第二个SQL语句,你可以在你的代码中动态构建,所以它应该是直截了当地使用。
我不知道,如果这个工程在SQL Server 2000中,但你可以尝试一下:
--combine parent and child, children are CSV onto parent row
CREATE TABLE #TableA (RowID int, Value1 varchar(5), Value2 varchar(5))
INSERT INTO #TableA VALUES (1,'aaaaa','A')
INSERT INTO #TableA VALUES (2,'bbbbb','B')
INSERT INTO #TableA VALUES (3,'ccccc','C')
CREATE TABLE #TableB (RowID int, TypeOf varchar(10))
INSERT INTO #TableB VALUES (1,'wood')
INSERT INTO #TableB VALUES (2,'wood')
INSERT INTO #TableB VALUES (2,'steel')
INSERT INTO #TableB VALUES (2,'rock')
INSERT INTO #TableB VALUES (3,'plastic')
INSERT INTO #TableB VALUES (3,'paper')
SELECT
a.*,dt.CombinedValue
FROM #TableA a
LEFT OUTER JOIN (SELECT
c1.RowID
,STUFF(
(SELECT
', ' + TypeOf
FROM (SELECT
a.RowID,a.Value1,a.Value2,b.TypeOf
FROM #TableA a
LEFT OUTER JOIN #TableB b ON a.RowID=b.RowID
) c2
WHERE c2.rowid=c1.rowid
ORDER BY c1.RowID, TypeOf
FOR XML PATH('')
)
,1,2, ''
) AS CombinedValue
FROM (SELECT
a.RowID,a.Value1,a.Value2,b.TypeOf
FROM #TableA a
LEFT OUTER JOIN #TableB b ON a.RowID=b.RowID
) c1
GROUP BY RowID
) dt ON a.RowID=dt.RowID
从SQL Server 2005输出:
RowID Value1 Value2 CombinedValue
----------- ------ ------ ------------------
1 aaaaa A wood
2 bbbbb B rock, steel, wood
3 ccccc C paper, plastic
(3 row(s) affected)
修改查询取代了用FOR XML RAW XML路径,所以这应该在SQL Server上运行2000
SELECT
a.*,dt.CombinedValue
FROM #TableA a
LEFT OUTER JOIN (SELECT
c1.RowID
,STUFF(REPLACE(REPLACE(
(SELECT
', ' + TypeOf as value
FROM (SELECT
a.RowID,a.Value1,a.Value2,b.TypeOf
FROM #TableA a
LEFT OUTER JOIN #TableB b ON a.RowID=b.RowID
) c2
WHERE c2.rowid=c1.rowid
ORDER BY c1.RowID, TypeOf
FOR XML RAW
)
,'<row value="',''),'"/>','')
, 1, 2, '') AS CombinedValue
FROM (SELECT
a.RowID,a.Value1,a.Value2,b.TypeOf
FROM #TableA a
LEFT OUTER JOIN #TableB b ON a.RowID=b.RowID
) c1
GROUP BY RowID
) dt ON a.RowID=dt.RowID
OUTPUT,相同的原始查询