【问题标题】:Pivot Query for Attendance考勤数据透视查询
【发布时间】:2019-05-19 13:51:49
【问题描述】:

我有一个包含 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

Here is my current output

我想要的输出,如果值为空,则应将其替换为状态“P”,如果某一天是星期日,则应将其替换为状态“S”,还应根据所选月份日期生成天数。

【问题讨论】:

  • 您的问题是什么?你已经说了你想要什么,但没有问任何问题。对于你想要做什么,看看ISNULLCASE 表达式。
  • @Ali Kazmi 这不能通过动态sql来完成吗?
  • @Tony Mathew 任何解决方案无论是动态的还是非动态的都可以提供帮助:)

标签: sql-server pivot


【解决方案1】:

我的想法是:

  • 找出月份的日期
  • 形成一个变量(@DaySelector)来选择列;这包括星期日应该具有值“P”的逻辑
  • 使用 PIVOT 将上述变量应用到动态查询中

下面是一个证明它的查询(tempdb)。我假设您的表是临时表“#tblAttendance”。样本数据中有两次缺勤,4 月 20 日缺席的学生 ID 1 和 15 日缺席的学生 ID 12:

/* 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”

【讨论】:

  • 执行sql脚本时出错'FORMAT'不是可识别的内置函数名。
  • 您使用的是什么版本的 SQL Server?
  • sql server 2008
  • Ms Sql server 2008 R2 可以设置转换功能而不是格式,因为支持转换。我正在尝试通过转换来做到这一点,但仍然没有运气。
  • 无法获取 2008 服务器。我认为它将与 CAST 一起使用。可以试试更新后的代码吗?
猜你喜欢
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多