简体   繁体   English

在SQL Server 2008中将行转换为列

[英]Convert Rows to Column In SQL Server 2008

I want to use Pivot to convert rows to columns. 我想使用Pivot将行转换为列。

I have three tables: 我有三个表:

  1. Student table with columns StudentID and StudentName 带有列StudentIDStudentName Student
  2. Subject table with columns SubjectID and SubjectName Subject表中包含SubjectIDSubjectName
  3. Student Subject table with columns StudentSubjectID , StudentID , SubjectID and Date Student Subject的列表StudentSubjectIDStudentIDSubjectIDDate

Now I wrote a query to get data from the above tables 现在,我编写了一个查询以从上述表中获取数据

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

Now I will make a monthly report to display Student Subject per month and output should be 现在,我将制作一个月度报告以显示每月的“学生主题”,输出应为

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             -                 -                  -                                                -

How can I do this? 我怎样才能做到这一点?

Thank you 谢谢

I guess the script will require too complex dynamic coding, I had just created a schema but will take too much effort to convert for a complete dynamic SQL script 我猜该脚本将需要太复杂的动态编码,我刚刚创建了一个架构,但是要花费太多的精力来转换为完整的动态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

I hope it helps somehow, But I guess after SQL concatenation of subjectname fields, the below query can be solved by a dynamic sql pivot 我希望它能以某种方式有所帮助,但是我想在将主体名称字段进行SQL串联之后,可以通过动态sql数据透视表解决以下查询

在此处输入图片说明

Please check following dynamic SQL pivot query 请检查以下动态SQL数据透视查询

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)

Here is my output 这是我的输出

在此处输入图片说明

To summarize the query, first of all I need the current month's dates as column names. 总结一下查询,首先我需要将当月的日期作为列名。 I used the calendar function module GetFullMonth at given reference. 我在给定的参考中使用了日历功能模块 GetFullMonth。 I just changed the return "datetime" column to "date" data type. 我只是将返回的“ datetime”列更改为“ date”数据类型。

As I noted in my previous code sample, I used SQL concatenation with FOR XML PATH method. 正如我在先前的代码示例中指出的那样,我将SQL串联与FOR XML PATH方法结合使用。

One last reference I'ld like to share with you. 我想与您分享最后一个参考。 I used date to string conversion in the PivotColumnHeaders section of the dynamic query where I define the additional pivot columns. 我在动态查询的PivotColumnHeaders部分中使用了日期到字符串的转换,在其中定义了其他数据透视列。 I used the conversion parameter as 23. You can check for a full list of datetime format parameter at given reference. 我使用的转换参数为23。您可以在给定的参考处检查datetime格式参数的完整列表。

I hope these helps you for the solution, 希望这些对您有所帮助,

If you want to date column contains only what has your table, then you have to use this query. 如果要日期列仅包含表中的内容,则必须使用此查询。 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)

   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,'+@col2+'  FROM #tt
    PIVOT(max(SubjectName) FOR [DateTime] IN ('+@col1+')) 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    -   -   -   -   -   -   -   -

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM