学生出勤报告逐月SQL查询

时间:2018-01-12 08:11:33

标签: sql asp.net sql-server sql-server-2014 dynamic-sql

有3个表 -

Attendance (EnrollmentNo,SubjectCode,Date,Attendance)

Student (EnrollmentNo, RollNo), 

UserDetails(EnrollmentNo,FirstName,LastName).

现在我想要的是按月分别显示出席次数,将卷号,名称,日期作为列,并将Student.RollNo,UserDetails.FirstName,UserDetails.LastName,Attendance.Attendance分别作为列的数据。

但我面临的问题是如何动态生成日期列并将出勤数据放在相应的日期列中。

Input - Startdate and Enddate

Expected Output -
-------------------------------------------------------
| Roll No |       Name       | 01-09-2018 | 01-12-2018|
-------------------------------------------------------
|    15   |   Suyash Gupta   |     1      |     0     |
-------------------------------------------------------
|    24   |  Himanshu Shukla |     2      |     2     |
-------------------------------------------------------
|    32   | Dhruv Raj Sirohi |     1      |     1     |
-------------------------------------------------------

这是我的方法 -

DECLARE @startdate date
DECLARE @enddate date

SET @startdate = convert(date,'01-09-2018')
SET @enddate = convert(date,'01-12-2018')

;with cte (@startdate, @enddate) as /*I don't know how to pass my date range 
                                    in cte() as this takes table column*/
(
    select 1
    union all
    select dateadd(dd, 1, startdate)
    from cte
    where startdate <= enddate
) 
select c.startdate
into #tempDates
from cte c


select @cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), 
startdate, 120)) 
                    from #tempDates
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT RollNo,FirstName,LastName, ' + @cols + ' from 
             (
                select S.RollNo,U.FirstName,U.LastName,
                D.startdate,
                convert(CHAR(10), startdate, 120) PivotDate
                from #tempDates D
                left join Attendance A
                on D.startdate = A.Date
            ) x
           pivot 
           (
                count(startdate)
                for PivotDate in (' + @cols + ')
           ) p '

execute(@query)

3 个答案:

答案 0 :(得分:1)

你的意思是这样的:

DECLARE @StartDate AS DATETIME, @EndDate AS DATETIME
SET @StartDate='2018-01-01'
SET @EndDate='2018-01-10'

SELECT Student.RollNo, Student.FirstName, Student.LastName, Attendance.Date
FROM Attendance,Student,UserDetails
WHERE Attendance.EnrollmentNo=Student.EnrollmentNo
AND UserDetails.EnrollmentNo=Student.EnrollmentNo
AND Attendance.[Date] between @StartDate and @EndDate

<强>更新

根据您在问题中所说的内容,您可能需要以下代码:

SELECT Student.RollNo, Student.FirstName, Student.LastName, 
STUFF((SELECT  ','+CAST([DATE] AS VARCHAR(30))
FROM Attendance
WHERE Attendance.EnrollmentNo=Student.EnrollmentNo
AND Attendance.[Date] between @StartDate AND @EndDate
FOR XML PATH('')
), 1, 1, '') Dates
FROM Student,UserDetails
WHERE UserDetails.EnrollmentNo=Student.EnrollmentNo

答案 1 :(得分:1)

您的代码存在一些问题,请查看代码中的差异:

DECLARE @startdate date = '20180109';
DECLARE @enddate date = '20180112';
DECLARE @cols as varchar(2000);
DECLARE @query as varchar(MAX);

WITH cte (startdate)
AS 
(SELECT
        @startdate AS startdate
    UNION ALL
    SELECT
        DATEADD(DAY, 1, startdate) AS startdate
    FROM cte
    WHERE startdate < @enddate)

SELECT
    @cols = STUFF((SELECT DISTINCT
            ',' + QUOTENAME(CONVERT(CHAR(10),
            startdate, 120))
        FROM cte
        FOR XML PATH (''), TYPE)
    .value('.', 'NVARCHAR(MAX)')
    , 1, 1, '')

SET @query = 'SELECT RollNo,FirstName,LastName, ' + @cols + ' from 
             (
                select S.RollNo,U.FirstName,U.LastName,
                D.startdate,
                convert(CHAR(10), startdate, 120) PivotDate
                from #tempDates D
                left join Attendance A
                on D.startdate = A.Date
            ) x
           pivot 
           (
                count(startdate)
                for PivotDate in (' + @cols + ')
           ) p '

EXECUTE (@query)

答案 2 :(得分:0)

这是运行代码并给我所需的输出。我要感谢Lobo,他纠正了我,以及其他所有努力帮助我的人。谢谢大家和stackoverflow谁为我提供了查询我面临的问题的平台。

DECLARE @startdate date = '20180109';
DECLARE @enddate date = '20180112';
DECLARE @cols as varchar(2000);
DECLARE @query as varchar(MAX);

WITH cte (startdate)
AS 
(SELECT
        @startdate AS startdate
    UNION ALL
    SELECT
        DATEADD(DAY, 1, startdate) AS startdate
    FROM cte
    WHERE startdate < @enddate
)
select c.startdate
into #tempDates
from cte c

SELECT
    @cols = STUFF((SELECT DISTINCT
            ',' + QUOTENAME(CONVERT(CHAR(10),
            startdate, 120))
        FROM #tempDates
        FOR XML PATH (''), TYPE)
    .value('.', 'NVARCHAR(MAX)')
    , 1, 1, '')

SET @query = 'SELECT RollNo,FirstName,LastName, ' + @cols + ' from 
             (
                select S.RollNo,U.FirstName,U.LastName,
                D.startdate,
                convert(CHAR(10), startdate, 120) PivotDate
                from #tempDates D,Attendance A, Student S, UserDetails U
                where D.startdate = A.Date and A.EnrollmentNo=S.EnrollmentNo and A.EnrollmentNo=U.userID
            ) x
           pivot 
           (
                count(startdate)
                for PivotDate in (' + @cols + ')
           ) p '

EXECUTE (@query)
drop table #tempDates