我想使用Pivot
将行转换为列。
我有三张桌子:
Student
表格,其中包含StudentID
列和StudentName
Subject
表格,其中包含SubjectID
列和SubjectName
Student Subject
表包含StudentSubjectID
,StudentID
,SubjectID
和Date
现在我写了一个查询来从上面的表中获取数据
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 :(得分: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 pivot来解决
答案 1 :(得分:0)
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)
这是我的输出
要总结查询,首先我需要将当前月份的日期作为列名。我在给定的引用中使用了calendar function module GetFullMonth。我刚刚更改了返回" datetime"列到"日期"数据类型。
正如我在之前的代码示例中所提到的,我使用SQL串联和FOR XML PATH方法。
最后一个参考资料我想与您分享。我在动态查询的PivotColumnHeaders部分中使用date来进行字符串转换,我在其中定义了其他数据透视表列。我使用转换参数为23。 您可以在给定参考位置检查datetime format parameter的完整列表。
我希望这些可以帮助您解决问题,
答案 2 :(得分: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)
答案 3 :(得分: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,'+@col2+' FROM #tt
PIVOT(max(SubjectName) FOR [DateTime] IN ('+@col1+')) p'
EXEC (@sql)
- 部分栏目 -
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 - - - - - - - -