【问题标题】:Student Attendance Report Month-wise SQL Query学生出勤报表按月SQL查询
【发布时间】:2018-01-13 04:46:22
【问题描述】:

有 3 张桌子 -

Attendance (EnrollmentNo,SubjectCode,Date,Attendance)

Student (EnrollmentNo, RollNo), 

UserDetails(EnrollmentNo,FirstName,LastName).

现在我想要的是按月显示出勤率,以 Roll No、Name、dates 作为列,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)

【问题讨论】:

  • 您能否展示当前的标记和代码以尝试满足您的要求?在这里,您应该先尝试一下,然后再询问当前设置出了什么问题。
  • 没错!展示您已经尝试过的内容以及失败的地方。
  • 我已经在上面添加了我的方法。

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


【解决方案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】:

你的意思是这样的:

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

【讨论】:

  • 不,我不想将日期作为列。我希望 date 的值作为单独的列,并希望在这些列中显示 Attendance.Attendance。
  • 你没有得到我。请参考上面的预期输出。
【解决方案3】:

这是运行代码并为我提供所需的输出。我要感谢纠正我的 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

【讨论】:

    猜你喜欢
    • 2021-12-05
    • 1970-01-01
    • 2021-05-09
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多