【问题标题】:Calculate percentage of results in week ranges starting from date计算从日期开始的周范围内的结果百分比
【发布时间】:2018-03-27 13:10:03
【问题描述】:

我有一个数据表,其中包含以下列显示出勤率。

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

我不确定从哪里开始输出这些数据,如下所示:

学生ID |第 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”附近的语法不正确。”

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

【问题讨论】:

  • 如果您还没有这样做,请查看 PIVOT 表 - 它们有时有点复杂,但对于将行转换为列很有用。
  • 您需要使用BETWEEN 将#CombinedAttClSe 与Weeks 间隔连接起来,然后使用动态SQL 旋转结果(因为您不知道您的参数将包括多少周)。跨度>
  • @EzequielLopezPetrucci 您好 Ezeuiel,我不确定我是否理解您所说的“以周间隔加入 #CombinedAttClSe”是什么意思。对不起,如果我遗漏了一些简单的东西,但你能进一步解释吗?
  • 我猜该表 #CombinedAttClSe 包含每个学生在特定日期的出勤率。如果是这样,您需要将该表与第二个查询中的最后一个查询(具有 WkNo 和 Min/Max 日期的那个)连接起来,这样您就可以知道学生每周的出勤率。
  • 是的,这行得通。只需确保“xCount”列(在您提到的链接中)在旋转之前已经包含出勤率。

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


【解决方案1】:

很遗憾,您不能在 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);

【讨论】:

  • 非常感谢。绝对回答了我的问题,并在此过程中提供了很好的指导以帮助我理解。
  • 很高兴为您提供帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多