Pivot Query for Attendance - PullRequest
       6

Pivot Query for Attendance

0 голосов
/ 19 мая 2019

У меня есть таблица посещаемости со столбцами studentid, atDate и status, которая сохраняет статус только для отсутствующих учащихся. учащиеся без статуса считаются присутствующими на дату регистрации посещаемости. Мне нужно показать посещаемость студентов. Ниже мой запрос, который успешно генерирует записи о посещаемости за выбранный месяц. проблема в том, что я не могу генерировать дни в выбранном месяце динамически, так как каждый месяц имеет разное количество дней. плюс я хочу показать статус для воскресенья как 'S'

SELECT fkStudentID, [1], [2], [3], [4],[5], [6], [7], [8], [9],
       [10],  [11], [12], [13], [14],[15], [16], [17], [18], [19],
       [20], [21], [22], [23], [24],[25], [26], [27], [28], [29],[30], [31]
FROM(
    Select 
       fkStudentID, Status, DAY(Dated) as [DayValue] 
  From tblAttendance Where Month(Dated) = Month(@Dated) and Year(Dated) = Year(@Dated) and fkClassID = 1
) AS studAttd
PIVOT
(
    MAX(Status)
    FOR [DayValue] IN ([1], [2], [3], [4],[5], [6], [7], [8], [9],
       [10],  [11], [12], [13], [14],[15], [16], [17], [18], [19],
       [20], [21], [22], [23], [24],[25], [26], [27], [28], [29],[30], [31])
) AS pvt

Вот мой токовый выход

Вывод My Desired, если значение равно нулю, его следует заменить на статус «P», а если день - на воскресенье, его следует заменить на статус «S»; также должно быть создано количество дней в соответствии с выбранным месяцем даты.

1 Ответ

0 голосов
/ 25 мая 2019

Моя идея была:

  • Найти даты месяца
  • Сформировать переменную (@DaySelector) для выбора столбцов;это включает логику, где воскресенья должны иметь значение 'P'
  • . Применить вышеуказанную переменную в динамический запрос с PIVOT

Ниже приведен запрос для подтверждения этого (tempdb).Я принял вашу таблицу в качестве временной таблицы "#tblAttendance".В данных выборки есть два пропуска: Идентификатор студента 1 отсутствовал 20 апреля и Идентификатор студента 12 15:

/* Your table*/
DROP TABLE #tblAttendance
CREATE TABLE #tblAttendance(fkStudentID int, Status varchar(20), Dated date)

/* The date to probe */
DECLARE @Dated AS date = '01-Apr-2019',
    @Days varchar(1000), @DaySelector varchar(2000);

/* Mock data: Student Id: 1 is absent on 20th April; Id 12 is Absent on 15th */
INSERT INTO #tblAttendance (fkStudentID, Status, Dated)
SELECT *
FROM (VALUES 
    (1, 'Absent', '20-Apr-2019'),
    (12, 'Absent', '15-Apr-2019')

) AS V1(fkStudentID, Status, Dated)

/* Fetch the days of the month */
SELECT @Days = COALESCE(@Days + ',', '') + QUOTENAME(CAST(Number + 1 AS VARCHAR(5))),

        -- Form a column selector for day's values; to be used in the dynamic query
        @DaySelector = COALESCE(@DaySelector + ',', '') + IIF(d.Day_Name = 'Sunday', 
            '''S'' AS ' + QUOTENAME(CAST(Number + 1 AS VARCHAR(5))),                                                            -- Value 'S' for Sundays        
            'ISNULL(' + QUOTENAME(CAST(Number + 1 AS VARCHAR(5))) + ', ''P'') AS ' + QUOTENAME(CAST(Number + 1 AS VARCHAR(5)))  -- 'P' for NULLs
        )
FROM master..spt_values
CROSS APPLY (

    -- Find out day names
    SELECT DATENAME(weekday, CAST(YEAR(@Dated) AS varchar(4)) + RIGHT('00' + CAST(MONTH(@Dated) AS varchar(2)), 2) + RIGHT('00' + CAST([number] + 1 AS VARCHAR(2)), 2)) AS Day_Name
    ) AS d
WHERE type = 'P'
AND
(CAST(CAST(YEAR(@Dated) AS VARCHAR) + '-' + CAST(MONTH(@Dated) AS VARCHAR) + '-01' AS DATETIME) + Number)
<
DATEADD(mm,1,CAST(CAST(YEAR(@Dated) AS VARCHAR) + '-' + CAST(MONTH(@Dated) AS VARCHAR) + '-01' AS DATETIME))

/* Prepare dynamic SQL */
DECLARE @SQL AS nvarchar(MAX)
    SET @SQL = 
    'WITH PIVOT_DATA AS (' +
        'SELECT fkStudentID, ' + @Days + ' ' +

        'FROM('+
            'SELECT '+
               'fkStudentID, Status, DAY(Dated) as [DayValue] '+
          'From #tblAttendance Where MONTH(Dated) = MONTH(@Dated) and YEAR(Dated) = YEAR(@Dated)'+
        ') AS studAttd '+
        'PIVOT'+
        '('+
            'MAX(Status)'+
            'FOR [DayValue] IN (' + @Days + ')'+
        ') AS pvt' +
    ')' +
    ' SELECT fkStudentID, ' + @DaySelector + ' FROM PIVOT_DATA'

PRINT @SQL
EXEC sp_executesql @stmt = @SQL, @params = N'@Dated date, @Days varchar(1000)', @Dated = @Dated, @Days = @Days

Примечание: - Я исключил ваше условие "fkClassID = 1" для краткости

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...