计算从日期开始的周范围内的结果百分比

时间:2018-03-27 13:10:03

标签: sql sql-server pivot pivot-table dynamic-sql

我有一个数据表,显示出席以下列。

PupilID,AttendanceDate,AttendanceSession,IsInAttendance(1或0)

我需要能够定义一个开始日期和结束日期(学期日期)来运行查询,这将显示每周每个学生的出勤率。

我可以使用以下代码找到每个学生的总百分比:

SELECT
    PupilID,
    ((SUM(CASE WHEN IsInAttendance = 1 THEN 1 ELSE 0 END) * 100) / COUNT(IsInAttendance))  AS TotalAttPct
FROM #CombinedAttClSe
GROUP BY PupilID

我有一年中的几周有以下代码:

DECLARE @StartDate DATETIME = '2011-09-01 00:00:00.000';
DECLARE @EndDate DATETIME = '2011-12-31 00:00:00.000';

;WITH GetDates AS
(
    SELECT
        DATEADD(DAY, 0, @startdate) AS TheDate,
        DATEPART(WK, DATEADD(DAY, 1, @startdate)) WkNo,
        DATEPART(YEAR, DATEADD(DAY, 1, @startdate)) DateYear
    UNION ALL
    SELECT
        DATEADD(DAY, 1, TheDate),
        DATEPART(WK, DATEADD(DAY, 1, TheDate)),
        DATEPART(YEAR, DATEADD(DAY, 1, TheDate))
        FROM GetDates
        WHERE TheDate < @enddate
)

SELECT
    WkNo,
    MIN(TheDate) AS SoW,
    MAX(TheDate) AS EoW
FROM GETDATES
GROUP BY WKNO
OPTION (MAXRECURSION 0);

我不知道从哪里开始输出这些数据如下:

PupilID |第1周|第2周|第3周|第4周|等

每个“周”标题都包含一个数字,以显示出席率。

编辑:

从用户建议我尝试使用PIVOT表和动态SQL来解决这个问题,但遇到了一些问题。下面是我到目前为止的代码。

CREATE TABLE #yt 
(
  [PupilID] int, 
  [WeekNo] int, 
  [IsInAttendance] int
);

INSERT INTO #yt
(
  [PupilID], 
  [WeekNo],
  [IsInAttendance]
)
VALUES
    (102, 1, 1),
    (102, 1, 1),
    (102, 1, 1),
    (102, 1, 1),
    (102, 1, 0),
    (102, 1, 1),
    (102, 1, 0),
    (102, 1, 1),
    (102, 2, 1),
    (102, 2, 1),
    (102, 2, 1),
    (102, 2, 1),
    (102, 2, 1),
    (102, 2, 1),
    (102, 2, 0),
    (102, 2, 1),
    (101, 1, 1),
    (101, 1, 1),
    (101, 1, 1),
    (101, 1, 1),
    (101, 1, 1),
    (101, 1, 1),
    (101, 1, 1),
    (101, 2, 1),
    (101, 2, 1),
    (101, 2, 1),
    (101, 2, 1),
    (101, 2, 0)

DECLARE @WkCols AS NVARCHAR(MAX),
        @WkQuery AS NVARCHAR(MAX)

select @WkCols = STUFF((SELECT ',' + QUOTENAME(WeekNo) 
                    FROM #yt
                    GROUP BY WeekNo
                    ORDER BY WeekNo
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @WkQuery = 'SELECT PupilID,' + @WkCols + ' FROM 
            (
                SELECT PupilID, WeekNo, IsInAttendance
                FROM #yt
            ) x
            PIVOT 
            (
                SUM(CASE WHEN IsInAttendance = 1 THEN 1 ELSE 0 END) * 100 / COUNT(IsInAttendance) 
                FOR WeekNo IN (' + @WkCols + ')
            ) p '

execute(@WkQuery);

目前我收到错误'关键字'CASE'附近的语法错误。'

任何指针或帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

不幸的是,您无法在PIVOT聚合函数上应用复杂聚合。因此,您必须使用简单的SUMMAX。尝试在转动前计算出勤率:

SELECT
    T.PupilID,
    T.WeekNo,
    AttendancePercentage = SUM(T.IsInAttendance) * 100.0 / COUNT(1)
FROM
    #yt AS T
GROUP BY
    T.PupilID,
    T.WeekNo

枢轴:

DECLARE @WkCols AS NVARCHAR(MAX),
        @WkQuery AS NVARCHAR(MAX)

select @WkCols = STUFF((SELECT ',' + QUOTENAME(WeekNo) 
                    FROM #yt
                    GROUP BY WeekNo
                    ORDER BY WeekNo
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @WkQuery = 'SELECT PupilID,' + @WkCols + ' FROM 
            (
                SELECT
                    T.PupilID,
                    T.WeekNo,
                    AttendancePercentage = SUM(T.IsInAttendance) * 100.0 / COUNT(1)
                FROM
                    #yt AS T
                GROUP BY
                    T.PupilID,
                    T.WeekNo
            ) x
            PIVOT 
            (
                MAX(AttendancePercentage) 
                FOR WeekNo IN (' + @WkCols + ')
            ) p '

execute(@WkQuery);