2017-01-04 71 views
0

我想使用Pivot將行轉換爲列。將行轉換爲SQL Server 2008中的列

我有三個表:

  1. StudentStudentID列和StudentName
  2. SubjectSubjectID列和SubjectName
  3. Student Subject的列StudentSubjectIDStudentIDSubjectIDDate

現在,我寫了一個查詢,以便從上表

StudentID StudentName SubjectID SubjectName DateTime 
-----------------------------------------------------------  
1   Yasser   1  Math   1/1/2017 
1   Yasser   1  English  1/1/2017 
1   Yasser   1  Math   3/1/2017 
1   Mark    1  Math   1/1/2017 
1   John    1  Math   6/1/2017 

獲得的數據現在我會讓月度報告顯示,每月和輸出學生主體應

Student/Days 1/1/2017  2/1/2017  3/1/2017 4/1/2017 ......................................... 30/1/2017 (All days for month) 

Yasser     Math    -     Math   -            - 

          English    -    -     -            - 

Mark     Math    -     -     -            - 

我該怎麼辦這個?

謝謝

+0

看出來的動態樞軸 – TheGameiswar

+0

類似於[拆分SQL表成一列中基於值的多個表](HTTP://計算器的.com /問題/ 25673476 /分SQL的表 - 到 - 多表爲基礎的上值功能於一列) –

回答

0

我猜的腳本將需要太複雜的動態編碼, 我剛剛創建的模式,但會耗費太多精力,爲一個完整的動態SQL腳本

;with cte as (
select distinct StudentName, SubjectName, [DateTime] from studentCTE 
), cte2 as (
select 
    StudentName, 
    case when [DateTime] = '2017-01-01' then SubjectName else null end as '2017-01-01', 
    case when [DateTime] = '2017-03-01' then SubjectName else null end as '2017-03-01', 
    case when [DateTime] = '2017-06-01' then SubjectName else null end as '2017-06-01' 
from cte 
) 
SELECT distinct 
    StudentName, 
    STUFF(
    (
    SELECT 
     ',' + [2017-01-01] 
    FROM cte2 C 
    where c.StudentName = cte2.StudentName 
    FOR XML PATH('') 
    ), 1, 1, '' 
) As '2017-01-01', 
    STUFF(
    (
    SELECT 
     ',' + [2017-03-01] 
    FROM cte2 C 
    where c.StudentName = cte2.StudentName 
    FOR XML PATH('') 
    ), 1, 1, '' 
) As '2017-03-01', 
    STUFF(
    (
    SELECT 
     ',' + [2017-06-01] 
    FROM cte2 C 
    where c.StudentName = cte2.StudentName 
    FOR XML PATH('') 
    ), 1, 1, '' 
) As '2017-06-01' 
from cte2 

我轉換希望它有助於某種方式,但我猜SQL concatenation的主題名字段後,下面的查詢可以通過動態的sql數據庫來解決

enter image description here

0

請檢查下面dynamic SQL pivot query

DECLARE @PivotColumnHeaders VARCHAR(MAX) 
SELECT @PivotColumnHeaders = 
    COALESCE(
    @PivotColumnHeaders + ',[' + convert(nvarchar(20),date,23) + ']', 
    '[' + convert(nvarchar(20),date,23) + ']' 
) 
FROM dbo.GetFullMonth(getdate()) 


DECLARE @PivotTableSQL NVARCHAR(MAX) 
SET @PivotTableSQL = N' 
    SELECT * 
    FROM (
       select distinct StudentName, 
        STUFF(
        (
        SELECT 
         '','' + SubjectName 
        FROM studentCTE C 
        where c.StudentName = studentCTE.StudentName 
        and c.DateTime = studentCTE.DateTime 
        FOR XML PATH('''') 
        ), 1, 1, '''' 
       ) As Subjects 
        , [DateTime] 
       from studentCTE 
) AS PivotData 
    PIVOT (
    MAX(Subjects) 
    FOR [DateTime] IN (
     ' + @PivotColumnHeaders + ' 
    ) 
) AS PivotTable 
' 
EXECUTE(@PivotTableSQL) 

這裏是我的輸出

enter image description here

總結查詢,首先我需要當月的日期作爲列名。我使用了給定參考的GetFullMonth的calendar function module。我只是將返回「datetime」列更改爲「date」數據類型。

正如我在我以前的代碼示例中指出的,我使用了與FOR XML PATH方法的SQL連接。

我想與大家分享的最後一篇參考文獻。我在動態查詢的PivotColumnHeaders部分中使用了日期到字符串轉換,其中我定義了額外的透視列。我使用的轉換參數爲23. 您可以查看給定參考文獻的完整列表datetime format parameter

我希望這些可以幫助你解決,

0

如果你想約會列中只包含有什麼你的表,那麼你必須使用此查詢。 DECLARE @DYNQRY AS VARCHAR(MAX) ,@COL AS VARCHAR(MAX) SELECT @COL= ISNULL(@COL + ',','') + QUOTENAME(DATE) FROM (SELECT DISTINCT DATE FROM STUDENTSUBJECT) AS DATE SET @DYNQRY ='SELECT STUDENTNAME, ' + @COL + ' FROM (SELECT A.STUDENTID,STUDENTNAME,SUBJECTNAME,DATE FROM STUDENT A,SUBJECT B,STUDENTSUBJECT C WHERE A.STUDENTID=C.STUDENTID AND B.SUBJECTID=C.SUBJECTID )A PIVOT( MAX(SUBJECTNAME) FOR DATE IN (' + @COL + ') ) AS PVTTABLE' EXEC (@DYNQRY)

0
CREATE TABLE #tt(StudentID INT,StudentName VARCHAR(200),SubjectID INT,SubjectName VARCHAR(200),[DateTime]DATETIME) 
    INSERT INTO #tt 
    SELECT 1,'Yasser',1,'Math','01/01/2017' UNION 
    SELECT 1,'Yasser',1,'English','01/01/2017' UNION 
    SELECT 1,'Yasser',1,'Math','01/03/2017' UNION 
    SELECT 1,'Mark',1,'Math','01/01/2017' UNION 
    SELECT 1,'John',1,'Math','01/06/2017' 

      DECLARE @col1 VARCHAR(max),@col2 VARCHAR(max),@sql VARCHAR(max) 
    SELECT @col1=ISNULL(@col1+',','')+ t.d 
      ,@col2=ISNULL(@col2+',','')+'ISNULL('+ t.d +',''-'') AS '+t.d 
    FROM #tt 
    INNER JOIN master.dbo.spt_values AS sv ON sv.type='P' AND sv.number BETWEEN 0 AND 30 
    CROSS APPLY(VALUES('['+CONVERT(VARCHAR,DATEADD(dd,sv.number,DATEADD(MONTH, MONTH([DateTime])-1,DATEADD(YEAR,YEAR([DateTime])-1900,0))),110)+']')) t(d) 
    WHERE MONTH(DATEADD(dd,sv.number,DATEADD(MONTH, MONTH([DateTime])-1,DATEADD(YEAR,YEAR([DateTime])-1900,0))))= MONTH([DateTime]) 
    GROUP BY MONTH([DateTime]),YEAR([DateTime]),sv.number,t.d 
    PRINT @col2 
    SET @sql=' 
    SELECT StudentID,StudentName,'[email protected]+' FROM #tt 
    PIVOT(max(SubjectName) FOR [DateTime] IN ('[email protected]+')) p' 
    EXEC (@sql) 

--partial column--

 
StudentID StudentName 01-01-2017 01-02-2017 01-03-2017 01-04-2017 01-05-2017 01-06-2017 01-07-2017 01-08-2017 01-09-2017 01-10-2017 01-11-2017 
1 John - - - - - Math - - - - - 
1 Mark Math - - - - - - - - - - 
1 Yasser Math - Math - - - - - - - -