2009-05-24 79 views
1

我有一些數據表:加入動態樞軸(第2版)

類別

CategoryID  CategoryName 

1    Home 
2    Contact 
3    About 

位置

PositionID  PositionName 

1    Main menu 
2    Left menu 
3    Right menu 

...(新行可稍後添加)

CategoryPosition

CPID CID PID COrder 

1  1  1  1 
2  1  2  2 
3  1  3  3 
4  2  1  4 
5  2  3  5 

我怎樣才能使一個表像這樣:

CID CName  MainMenu LeftMenu RightMenu 

1  Home  1   2   3 
2  Contact 4   0   5 
3  About  0   0   0 

如果一個新的類別和位置排在後面添加,查詢應自動反映的改變,例如:

CID CName  MainMenu LeftMenu RightMenu BottomMenu 

1  Home  1   2   3   0 
2  Contact 4   0   5   0 
3  About  0   0   0   0 
4  News  0   0   0   0 
+0

你可以**解釋**你想完成什麼?剛剛列出一堆表格真的沒有多大幫助...... – 2009-05-24 17:09:57

回答

2

下面的動態查詢似乎工作:

declare @columnlist nvarchar(4000) 
select @columnlist = IsNull(@columnlist + ', ', '') + '[' + PositionName + ']' 
from #Position 

declare @query nvarchar(4000) 
select @query = ' 
    select * 
    from (
     select CategoryId, CategoryName, PositionName, 
       IsNull(COrder,0) as COrder 
     from #Position p 
     cross join #Category c 
     left join #CategoryPosition cp 
       on cp.pid = p.PositionId 
       and cp.cid = c.CategoryId 
    ) pv 
    PIVOT (max(COrder) FOR PositionName in (' + @columnlist + ')) as Y 
    ORDER BY CategoryId, CategoryName 
' 

exec sp_executesql @query 

一些澄清:

  • 的@columnlist包含dymamic字段列表,從持倉表
  • 的交叉連接建立創建所有類別和所有位置的列表
  • 左連接查找相應的COrder
  • MAX()選擇每個類別+位置最高CORDER,如果有多於一個的
  • PIVOT()打開的各種PositionNames成單獨的列

P.S.我的表名以#開頭,因爲我將它們創建爲臨時表。刪除#以引用永久表。

P.S.2。如果有人想在此嘗試他的手,這裏是一個腳本,在這個問題上,以創建表:

set nocount on 

if object_id('tempdb..#Category') is not null drop table #Category 
create table #Category (
    CategoryId int identity, 
    CategoryName varchar(50) 
) 

insert into #Category (CategoryName) values ('Home') 
insert into #Category (CategoryName) values ('Contact') 
insert into #Category (CategoryName) values ('About') 
--insert into #Category (CategoryName) values ('News') 

if object_id('tempdb..#Position') is not null drop table #Position 
create table #Position (
    PositionID int identity, 
    PositionName varchar(50) 
) 

insert into #Position (PositionName) values ('Main menu') 
insert into #Position (PositionName) values ('Left menu') 
insert into #Position (PositionName) values ('Right menu') 
--insert into #Position (PositionName) values ('Bottom menu') 

if object_id('tempdb..#CategoryPosition') is not null 
    drop table #CategoryPosition 
create table #CategoryPosition (
    CPID int identity, 
    CID int, 
    PID int, 
    COrder int 
) 

insert into #CategoryPosition (CID, PID, COrder) values (1,1,1) 
insert into #CategoryPosition (CID, PID, COrder) values (1,2,2) 
insert into #CategoryPosition (CID, PID, COrder) values (1,3,3) 
insert into #CategoryPosition (CID, PID, COrder) values (2,1,4) 
insert into #CategoryPosition (CID, PID, COrder) values (2,3,5) 
0

我想你需要選擇使用PIVOT。默認情況下,pivot只能選擇一列靜態列。網上有一些處理動態柱樞軸的解決方案,如herehere

1

正如一些海報中提到,使用轉動命令動態SQL是要走的路。我寫了一個名爲pivot_query.sql的存儲過程,這個過程非常方便。它的工作原理是這樣的:

-- Define a query of the raw data and put it in a variable (no pre-grouping required) 
declare @myQuery varchar(MAX); 

set @myQuery = ' 
select 
    cp.cid, 
    c.CategoryName, 
    p.PositionName, 
    cp.COrder 
from 
    CategoryPosition cp 

    JOIN Category c 
     on (c.CategoryId = cp.cid) 

    JOIN Position p 
     on (p.PositionId = cp.pid)'; 

-- Call the proc, passing the query, row fields, pivot column and summary function 
exec dbo.pivot_query @myQuery, 'CategoryName', 'PositionName', 'max(COrder) COrder' 

的pivot_query調用的完整語法爲:

pivot_query '<query>', '<field list for each row>', '<pivot column>', '<aggregate expression list>', '[<results table>]', '[<show query>]' 

它在source code頂部解釋更多的評論。

這個過程的幾個優點是你可以指定多個彙總函數,如max(COrder),min(COrder)等,它可以選擇將輸出存儲在表中以防你想加入彙總數據和其他信息。

0

我的建議是將您的數據作爲簡單的連接返回,並讓前端將其整理出來。有些東西是SQL很好的,但是這個特殊的問題看起來像是前端應該做的事情。當然,如果不知道你的全部情況,我都不知道,但那是我的直覺。