2015-09-25 47 views
0

我想寫一個具有可變列數的查詢,具體取決於數據,但我從來沒有做過這種事情。如何做一個交叉表列的數量變化? (ADO SQL Server)

我們正在運行的ADO,希望有一個單一的查詢(可能與子查詢),但沒有其他的編碼或GO語句,存儲過程等

我們打算使用此查詢的結果一個可編輯的網格。

下面是我們的數據樣本。我們有一份員工名單和一份項目清單。請注意,這不是一個「總結」交叉表。每個單元只有一個源代碼。

我們希望查詢結果對每個項目都有一列。該列中的單元格將包含該項目上該員工的小時數。

如果我們添加一個項目,我們希望另一列出現在查詢結果中。

編輯:由於我們在代碼中編寫查詢並提交它,我們可以動態生成查詢。我們不需要動態生成代碼。例如,在我們的下面的數據中,我們將能夠閱讀(用我們的母語)的項目表,並知道我們有3個項目和他們的名字是什麼。我們可以在透視我從閱讀起來看到使用它們,但只是不知道如何...

Crosstab source and results

+0

請發表您的嘗試,如果可能的話,在創建[SQLFiddle(http://sqlfiddle.com/)或[Rextester(http://rextester.com/一個樣機運行代碼)來輕鬆支持你 –

回答

3

怎麼是這樣的:​​

declare @pivotquery as nvarchar(max) 
declare @columnname as nvarchar(max) 
select @columnname= isnull(@columnname + ',','') 
     + quotename(name) 
from (select name from project) as t2 
set @pivotquery = 
    N'with t1 as (
     select ph.employee, e.name as empname, p.name, ph.hours 
     from project_hours ph 
     inner join project p 
     on p.id = ph.project 
     inner join employees e 
     on e.id = ph.employee 
     ) 
     select * 
     from t1 
     pivot(sum(hours) for name in (' + @columnname + ')) as pivot_table' 
exec sp_executesql @pivotquery 

有顯著幫助,進一步的解釋在這裏:http://sqlhints.com/2014/03/18/dynamic-pivot-in-sql-server/

編輯:當我再次讀你的問題時,我注意到你在代碼中建立查詢,在這種情況下,你可能不需要上述實用程序,但一個簡單的透視,你建立for name in子句中你的程序,就像這樣:http://sqlfiddle.com/#!6/2ded1/12

with t1 as (
    select ph.employee, e.name as empname, p.name, ph.hours 
    from project_hours ph 
    inner join project p 
    on p.id = ph.project 
    inner join employees e 
    on e.id = ph.employee 
) 
select * 
from t1 
pivot(sum(hours) 
     for name in ([First Floor], [Basement], [Parking Lot A])) 
     as hours_summary 
+0

謝謝你,肯德爾! – Tom

1

對於未來的讀者,這裏使用兩個嵌套派生表的子查詢一個一般化ANSI-SQL語法查詢。

這個查詢應該是大多數關係數據庫管理系統(SQL服務器,MySQL和SQLite的,甲骨文和PostgreSQL,DB2),因爲它不使用CTE窗口功能(WITH)或數據庫特有的功能,如SQL Server的Pivot()兼容:

SELECT [Key], [Employee Name], [Age], 
     Max(FF) As [First Floor], 
     Max(BSMT) As [Basement], 
     Max(PRKLotA) As [Parking Lot A]  
FROM (
    SELECT dT.Key, 
      dT.[Employee Name], 
      dT.[Age], 
      CASE WHEN dT.Project = 'First Floor' THEN dT.Hours END As FF, 
      CASE WHEN dT.Project = 'Basement' THEN dT.Hours END As BSMT, 
      CASE WHEN dT.Project = 'Parking Lot A' THEN dT.Hours END As PRKLotA 
    FROM (
      SELECT [Employees].Key, 
       [Employees.[Employee Name], 
       Employees.Age, Projects.Project, 
       [Project Hours].Hours 
      FROM [Project Hours] 
      INNER JOIN Employees ON [Project Hours].[Employees FK] = Employees.Key 
      INNER JOIN Projects ON [Project Hours].[Projects FK] = Projects.Key 
    ) AS dT 
) As dT2  
GROUP BY [Key], [Employee Name], [Age] 

輸出:

Key Employee Name Age First Floor  Basement Parking Lot A 
1   Tim  40   1000   3000  
2   John  5   2000   4000    5000