2009-12-24 60 views
2

讓我們asume我在SQL父子結構安裝(服務器2005年):獲取所有孩子的單親家庭中的單個行

CREATE TABLE parent (Id INT IDENTITY PRIMARY KEY, Name VARCHAR(255)) 
CREATE TABLE child (Id INT IDENTITY PRIMARY KEY, parentId INT, Name VARCHAR(255)) 

insert into parent select 'parent with 1 child' 
insert into parent select 'parent with 2 children' 

insert into child(name, parentid) select 'single child of parent 1', 1 
insert into child(name, parentid) select 'child 1 of 2 of parent 2', 2 
insert into child(name, parentid) select 'child 2 of 2 of parent 2', 2 

有沒有辦法爲每個父母返回一行與它的孩子作爲列?像:

parent.Id,parent.Name,兒童(1).ID,兒童(1).name和兒童(2).ID,兒童(2),請將.Name

與入門出來:

select * from parent p 
    left outer join child c1 on c1.parentid = p.id 
+0

你能標誌着這個答案對未來的遊客嗎? – Tanner 2014-05-13 08:43:08

回答

4

你舉的例子是接近旋轉,但我不認爲透視功能是在這一個可用。

我已將您的示例重命名爲使用「部門 - 人員」,而不是「孩子父母」,只是爲了保持我的理智。

所以,第一表和一些數據

DECLARE @Department TABLE 
    ( 
    DepartmentID int 
    ,DepartmentName varchar(50) 
) 
DECLARE @Person TABLE 
    ( 
    PersonID int 
    ,PersonName varchar(50) 
    ,DepartmentID int 
) 

INSERT INTO @Department 
    (DepartmentID, DepartmentName) 
SELECT 1, 'Accounting' UNION 
SELECT 2, 'Engineering' UNION 
SELECT 3, 'Sales' UNION 
SELECT 4, 'Marketing' ; 

INSERT INTO @Person 
    (PersonID, PersonName, DepartmentID) 
SELECT 1, 'Lyne', 1 UNION 
SELECT 2, 'Damir', 2 UNION 
SELECT 3, 'Sandy', 2 UNION 
SELECT 4, 'Steve', 3 UNION 
SELECT 5, 'Brian', 3 UNION 
SELECT 6, 'Susan', 3 UNION 
SELECT 7, 'Joe', 4 ; 

現在我想扁平化模型,我將使用臨時表,因爲我有表變量 - 但「真正的表」視圖將是一件好事太。

/* Create a table with: 
    DepartmentID, DepartmentName, PersonID, PersonName, PersonListIndex 

This could be a view instead of temp table. 
*/ 
IF object_id('tempdb.dbo.#tmpTbl','U') IS NOT NULL 
DROP TABLE #tmpTbl 

; 
WITH prs 
     AS (SELECT PersonID 
        ,PersonName 
        ,DepartmentID 
        ,row_number() OVER (PARTITION BY DepartmentID ORDER BY PersonID) AS [PersonListIndex] 
      FROM @Person 
      ), 
     dptprs 
     AS (SELECT d.DepartmentID 
        ,d.DepartmentName 
        ,p.PersonID 
        ,p.PersonName 
        ,p.PersonListIndex 
      FROM @Department AS d 
        JOIN prs AS p ON p.DepartmentID = d.DepartmentID 
      ) 
SELECT * INTO #tmpTbl FROM dptprs 

-- SELECT * FROM #tmpTbl 

動態列指動態查詢,我將撰寫這行到行插入表

/* Table to compose dynamic query */ 
DECLARE @qw TABLE 
    ( 
    id int IDENTITY(1, 1) 
    ,txt nvarchar(500) 
) 

/* Start composing dynamic query */ 
INSERT INTO @qw (txt) VALUES ('SELECT') 
INSERT INTO @qw (txt) VALUES ('[DepartmentID]') 
INSERT INTO @qw (txt) VALUES (',[DepartmentName]') ; 


/* fetch max number of employees in a department */ 
DECLARE @i int ,@m int 
SET @m = (SELECT max(PersonListIndex) FROM #tmpTbl) 

/* Compose dynamic query */ 
SET @i = 1 
WHILE @i <= @m 
    BEGIN 
     INSERT INTO @qw (txt) 
      SELECT ',MAX(CASE [PersonListIndex] WHEN ' 
        + cast(@i AS varchar(10)) + ' THEN [PersonID] ELSE NULL END) AS [Person_' 
        + cast(@i AS varchar(10)) + '_ID]' 

     INSERT INTO @qw (txt) 
      SELECT ',MAX(CASE [PersonListIndex] WHEN ' 
        + cast(@i AS varchar(10)) + ' THEN [PersonName] ELSE NULL END) AS [Person_' 
        + cast(@i AS varchar(10)) + '_Name]' 

    SET @i = @i + 1 
    END 

/* Finish the dynamic query */ 
INSERT INTO @qw (txt) VALUES ('FROM #tmpTbl') 
INSERT INTO @qw (txt) VALUES ('GROUP BY [DepartmentID], [DepartmentName]') 
INSERT INTO @qw (txt) VALUES ('ORDER BY [DepartmentID]') 

-- SELECT * FROM @qw 

現在連接所有查詢行到一個變量,並執行

/* Create a variable with dynamic sql*/ 
DECLARE @exe nvarchar(4000) 
SET @exe='' 
SELECT @exe = @exe + txt + ' ' FROM @qw ORDER BY id 

/* execute dynamic sql */ 
EXEC master..sp_executesql @exe 

這裏是結果:

alt text http://www.damirsystems.com/dp_images/morepivot_result_01.png

+0

不錯的例子!我會看看我是否可以在我的真實數據上使用它。謝謝! – edosoft 2009-12-25 13:34:02

+0

我需要做類似的事情。我得到一張Excel電子表格,將兩張表格中的數據拼合成一張表格。我使用這段代碼將子行轉換爲列。你爲我節省了很多時間。謝謝!!! – 2010-01-05 16:08:10

1

嘗試用動態樞轉

測試數據

declare @parent table (Id INT IDENTITY PRIMARY KEY, Name VARCHAR(255)) 
declare @child table (Id INT IDENTITY PRIMARY KEY, parentId INT, Name VARCHAR(255)) 

insert into @parent select 'parent with 1 child' 
insert into @parent select 'parent with 2 children' 
insert into @child(name, parentid) select 'single child of parent 1', 1 
insert into @child(name, parentid) select 'child 1 of 2 of parent 2', 2 
insert into @child(name, parentid) select 'child 2 of 2 of parent 2', 2 

查詢

declare @col_list varchar(max) 
declare @dynquery nvarchar(max) 
select 
c.Id as ChildId 
, p.Id as ParentId 
,p.Name as ParentName 
,c.Name as ChildName 
into #t from @parent p join @child c on p.Id = c.parentId 
select @col_list = stuff(cols,1,1,'') from 
(select distinct ',[' + cast(ChildName as varchar(50)) + ']' 
from #t for xml path(''))X(cols) 
set @dynquery = 'select * from #t pivot (max(ChildId) for ChildName in (' + @col_list + ') ' + ') as pvt' 
EXEC master..sp_executesql @dynquery 
drop table #t 

輸出:

ParentId ParentName child 1 of 2 of parent 2 child 2 of 2 of parent 2 single child of parent 1 
1 parent with 1 child NULL NULL 1 
2 parent with 2 children 2 3 NULL 
3

如果你想有一個不同的外觀試試這個

的樣本數據

declare @parent table (Id INT IDENTITY PRIMARY KEY, Name VARCHAR(255)) 
declare @child table (Id INT IDENTITY PRIMARY KEY, parentId INT, Name VARCHAR(255)) 

insert into @parent select 'parent with 1 child' 
insert into @parent select 'parent with 2 children' 
insert into @child(name, parentid) select 'single child of parent 1', 1 
insert into @child(name, parentid) select 'child 1 of 2 of parent 2', 2 
insert into @child(name, parentid) select 'child 2 of 2 of parent 2', 2 

查詢

select p.Id as ParentId,p.Name as ParentName 
    ,stuff((select ', ' + 'child(' + cast(c.Id as varchar(10)) + ') : ' + c.Name 
    from @child c where c.parentId = p.id for xml path('')),1,1,'') 'Child(id):Child Names' 
    from @parent p 
group by 
p.Id,p.Name 

輸出

ParentId ParentName Child(id):Child Names 
1 parent with 1 child child(1) : single child of parent 1 
2 parent with 2 children child(2) : child 1 of 2 of parent 2, child(3) : child 2 of 2 of parent 2 
1

看着達米爾Sudarevic的回答後,我想出了這個:(見我的表結構問題)

declare @family table (parentid int , parentname varchar(255), child1id int, child1name varchar(255), child2id int, child2name varchar(255)) 

insert into @family(parentid, parentname) 
select id, name from parent 

update @family set child1id = c.id, child1name = c.name 
from @family f, child c 
where c.parentid = f.parentid 

update @family set child2id = c.id, child2name = c.name 
from @family f, child c 
where c.parentid = f.parentid 
and not exists 
    (select child1id from @family where child1id = c.id) 

select * from @family