2011-09-29 51 views
1

嗨,并提前致谢。SQL Server表结果数组在SQL Server 2005中

首先,我不是说我想要将数组转换为表格。我可以做到这一点。简单:)

我想做相反的事情。

我在之间有一排与另一个表相关的行。我希望输出该行,然后在该行的单个列中,比如说Children,它的链接行在数组(或者我可以解释为具有前端代码的数组的字符串)中。

像这样:

ID TITLE DESCRIPTION CHILDREN 
-------------------------------------------------------- 
36 Blah Blah Blah  ['Bob','Gary','Reginald'] 
20 Pah  Pah Pah  ['Emily','Dave'] 

你明白吗?

我知道,这可能不是最好的办法。但是,这是一个特定用途,在这里解释时间太长。

再次感谢。

+1

可能的重复http://stackoverflow.com/questions/6899/is-there-a-way-to-create-a-sql-server-function-to-join-multiple-rows-from- a-sub – Seph

+0

是的,对不起。我的问题是我没有搜索拼接这个词! – jamesmhaley

回答

2

实际上,你可以做到这一切在一个CTE选择查询,而无需使用任何功能。具体方法如下:

首先,考虑这个父/子表结构:

CREATE TABLE P (ID INT PRIMARY KEY, Description VARCHAR(20)); 
CREATE TABLE C (ID INT PRIMARY KEY, PID INT, 
       Description VARCHAR(20), 
       CONSTRAINT fk FOREIGN KEY (PID) REFERENCES P(ID)); 

(!我已经使用P和C,以节省打字)

而且让我们添加一些测试数据,匹配该问题的提问者:

INSERT INTO P VALUES (36, 'Blah Blah'); 
INSERT INTO P VALUES (20, 'Pah Pah'); 

INSERT INTO C VALUES (1, 36, 'Bob'); 
INSERT INTO C VALUES (2, 36, 'Gary'); 
INSERT INTO C VALUES (3, 36, 'Reginald'); 
INSERT INTO C VALUES (4, 20, 'Emily'); 
INSERT INTO C VALUES (5, 20, 'Dave'); 

然后最后,CTE表达式:

WITH 
FirstItems (PID, FirstCID) AS ( 

    SELECT C.PID, MIN(C.ID) 
     FROM C 
    GROUP BY C.PID  
), 
SubItemList (PID, CID, ItemNum) AS (

    SELECT C.PID, C.ID, 1 
     FROM C JOIN FirstItems FI ON (C.ID = FI.FirstCID) 
    UNION ALL 
    SELECT C.PID, C.ID, IL.ItemNum + 1 
     FROM C JOIN SubItemList IL ON C.PID = IL.PID AND C.ID > CID 
), 
ItemList (PID, CID, ItemNum) AS (

    SELECT PID, CID, MAX(ItemNum) 
     FROM SubItemList 
    GROUP BY PID, CID 
), 
SubArrayList (PID, CID, Array, ItemNum) AS (

    SELECT IL.PID, IL.CID, CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum 
     FROM ItemList IL JOIN C ON IL.CID = C.ID 
    WHERE IL.ItemNum = 1 
    UNION ALL 
    SELECT IL.PID, IL.CID, AL.Array + ',' + CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum 
     FROM ItemList IL 
     JOIN SubArrayList AL ON (IL.PID = AL.PID AND IL.ItemNum = AL.ItemNum + 1) 
     JOIN C ON (IL.CID = C.ID) 
), 
MaxItems (PID, MaxItem) AS (

    SELECT PID, MAX(ItemNum) 
     FROM SubItemList 
    GROUP BY PID 

), 
ArrayList (PID, List) AS (

    SELECT SAL.PID, SAL.Array 
     FROM SubArrayList SAL 
     JOIN MaxItems MI ON (SAL.PID = MI.PID AND SAL.ItemNum = MI.MaxItem) 

) 
SELECT P.ID, P.Description, AL.List 
    FROM ArrayList AL JOIN P ON P.ID = AL.PID 
ORDER BY P.ID 

结果:

ID Description List 
-- -------------- -------- 
20 Pah Pah  Emily,Dave 
36 Blah Blah  Bob,Gary,Reginald 

为了解释这是怎么回事,我将介绍CTE的各个部分,然后它做什么。

FirstItems着眼于所有的孩子,发现每个父组最低ID为锚下一个递归使用SELECT:

FirstItems (PID, FirstCID) AS (
    SELECT C.PID, MIN(C.ID) 
     FROM C 
    GROUP BY C.PID 
) 

SubItemList是一个递归选择拿起从前面的查询最低的孩子,并分配一个递增的项目编号给每个孩子从1开始:

SubItemList (PID, CID, ItemNum) AS ( 
    SELECT C.PID, C.ID, 1 
     FROM C JOIN FirstItems FI ON (C.ID = FI.FirstCID) 
    UNION ALL 
    SELECT C.PID, C.ID, IL.ItemNum + 1 
     FROM C JOIN SubItemList IL ON C.PID = IL.PID AND C.ID > CID 
) 

麻烦的是它的DUP并代表吃了很多的项目,所以ITEMLIST滤波以随便挑最大的各组:

ItemList (PID, CID, ItemNum) AS (
SELECT PID, CID, MAX(ItemNum) 
    FROM SubItemList 
GROUP BY PID, CID 
) 

现在我们有父母的ID清单,每一个有孩子的编号从1到x的:

PID   CID   ItemNum 
----------- ----------- ----------- 
36   1   1 
36   2   2 
36   3   3 
20   4   1 
20   5   2 

SubArrayList带着孩子们行,递归地加入到号码列表,并启动所有附加的说明彼此,开始与一个单一的描述:

SubArrayList (PID, CID, Array, ItemNum) AS ( 
    SELECT IL.PID, IL.CID, CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum 
     FROM ItemList IL JOIN C ON IL.CID = C.ID 
    WHERE IL.ItemNum = 1 
    UNION ALL 
    SELECT IL.PID, IL.CID, AL.Array + ',' + CAST(C.Description AS VARCHAR(MAX)), IL.ItemNum 
     FROM ItemList IL 
     JOIN SubArrayList AL ON (IL.PID = AL.PID AND IL.ItemNum = AL.ItemNum + 1) 
     JOIN C ON (IL.CID = C.ID) 
) 

结果现在是:

PID   CID   Array    ItemNum 
----------- ----------- ----------------- ----------- 
36   1   Bob    1 
20   4   Emily    1 
20   5   Emily,Dave  2 
36   2   Bob,Gary   2 
36   3   Bob,Gary,Reginald 3 

因此,所有我们需要做的是摆脱所有的部分串联行。

MaxItems只是抓住家长的名单和他们的最高的项目数,这使得下面的查询简单一点:

MaxItems (PID, MaxItem) AS ( 
    SELECT PID, MAX(ItemNum) 
     FROM SubItemList 
    GROUP BY PID   
) 

ArrayList的进行使用了最大的部分串联行的最后扑杀

ArrayList (PID, List) AS (
SELECT SAL.PID, SAL.Array 
    FROM SubArrayList SAL 
    JOIN MaxItems MI ON (SAL.PID = MI.PID AND SAL.ItemNum = MI.MaxItem)  
) 

最后,剩下的是查询结果:

012项目数从以前的查询获得性
SELECT P.ID, P.Description, AL.List 
    FROM ArrayList AL JOIN P ON P.ID = AL.PID 
ORDER BY P.ID 
1

您需要一个函数,它在传递将子表链接到父项的外键时,查询子表以构建一个光标,然后循环连接所需的值。函数然后返回该字符串。函数然后被称为查询的第四列。不能帮助你的语法等,因为我不使用SQL服务器

+0

正是我需要的! – jamesmhaley