2009-09-29 14 views
4

我有一個父表和子表,並且想要創建一個Select語句,給定一個父ID,爲每個孩子返回該父母的行和附加行。當一個或多個孩子存在時,做一個左連接並不會讓我自己爲父母自己排隊。我知道這可以用UNION完成,但我正在尋找一個解決方案,不會使用union語句。這可能嗎?如何爲沒有UNION的子項選擇一個父行和額外的行?

[父表]

ID  Name 
------------- 
1 | Bob 

[子表]

ID  ParentId Name 
----------------------- 
1 | 1  | Jim  
2 | 1  | Ned 

查詢結果我在尋找:

Parent_Name Child_Name 
--------------------------- 
Bob   | NULL <- I need this null here 
Bob   | Jim 
Bob   | Ned 
+3

爲什麼你不希望使用某個工會嗎? – 2009-09-29 19:10:51

+0

你爲什麼要這樣做?無論你想要做什麼,肯定有更好的方法。 – erikkallen 2009-09-29 19:13:29

+1

如果深度是靜態的,則可以使用具有相同表格的連接。 – 2009-09-29 19:23:30

回答

7

有一個骯髒的黑客:

SELECT 
    P2.Name Parent_Name, 
    C.Name Child_Name 
FROM [Parent Table] P1 
    FULL OUTER JOIN [Child Table] C 
     ON 1=0 
    INNER JOIN [Parent Table] P2 
     ON IsNull(P1.ID,C.ParentId) = P2.ID 
WHERE P2.ID = *ID here* 

這應該給你你想要的結果...希望。

+0

+1大師答案,謝謝! – 2009-09-29 22:46:11

+0

+1,孩子桌上的FULL OUTER JOIN,好主意! – 2009-09-30 12:33:03

+0

謝謝。 :)當嘗試格式化「FOR XML AUTO」轉換的數據時,我遇到了類似的問題。 – 2009-09-30 12:49:22

2

你需要做的這一個時間表設置(如果您不想使用數字表,請參閱下面的替代解決方案):

SELECT TOP 10000 IDENTITY(int,1,1) AS Number 
    INTO Numbers 
    FROM sys.columns s1 
    CROSS JOIN sys.columns s2 
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) 

一旦Numbers表格設置,使用此查詢:

DECLARE @ParentTable table (ID int,Name varchar(20)) 
DECLARE @ChildTable table (ID int,ParentID int,Name varchar(20)) 
INSERT INTO @ParentTable VALUES (1,'Bob') 
INSERT INTO @ChildTable VALUES (1,1,'Jim') 
INSERT INTO @ChildTable VALUES (2,1,'Ned') 

SELECT DISTINCT 
    dt.Name,c.Name 
    FROM (SELECT 
       CASE WHEN n.Number=1 THEN NULL ELSE p.ID END AS ID,p.Name 
       FROM @ParentTable   p 
        INNER JOIN Numbers  n ON 1=1 
       WHERE p.ID=1 AND n.Number<=2 
     ) dt 
     LEFT OUTER JOIN @ChildTable c ON dt.ID=c.ParentID 
    ORDER BY 1,2 

OUTPUT:

Name     Name 
-------------------- -------------------- 
Bob     NULL 
Bob     Jim 
Bob     Ned 

(3 row(s) affected) 

替代解決方案,如果你不希望創建一個數字表,你可以使用此方法返回與上面相同的輸出:

SELECT DISTINCT 
    dt.Name,c.Name 
    FROM (SELECT 
       CASE WHEN n.Number=1 THEN NULL ELSE p.ID END AS ID,p.Name 
       FROM @ParentTable   p 
        INNER JOIN (SELECT ROW_NUMBER() OVER(ORDER BY object_id) AS Number FROM sys.columns) n ON n.Number<=2 
       WHERE p.ID=1 AND n.Number<=2 
     ) dt 
     LEFT OUTER JOIN @ChildTable c ON dt.ID=c.ParentID 
     ORDER BY 1,2 

我正在嘗試使用CTE來擴展父行,但是如果不使用UNION就很難!

0

foriamstu答案啓發我去尋找一個更簡單的答案:

DECLARE @ParentTable table (ID int, Name varchar(20)) 
DECLARE @ChildTable table (ID int,ParentID int, Name varchar(20)) 
INSERT INTO @ParentTable VALUES (1,'Bob') 
INSERT INTO @ChildTable VALUES (1,1,'Jim') 
INSERT INTO @ChildTable VALUES (2,1,'Ned') 

SELECT DISTINCT 
    P1.Name  Parent_Name, 
    C.Name  Child_Name 
FROM @ParentTable P1 
LEFT JOIN @ChildTable C2 ON C2.ParentID = P1.ID 
LEFT JOIN @ChildTable C ON C.ParentID = P1.ID AND C.ParentID = C2.ID 
WHERE P1.ID = 1 
+1

這不起作用,你會得到_Bob - Jim_和_Bob - Ned_行,但_Bob - null_行在哪裏? – 2009-09-30 12:34:06

+0

KM好抓+1。父表中至少需要兩行,但我只是做了更正。 – 2009-09-30 15:24:54

相關問題