Sql server 如何使用联接和Groupby编写透视查询

Sql server 如何使用联接和Groupby编写透视查询,sql-server,pivot-table,Sql Server,Pivot Table,您好,我已经创建了一个MS SQL查询,它正在生成完美的结果。但是我需要更改行和列的值。我在网上搜索并学习了PIVOT以改变方向。我已经创建了一些小的查询,但我无法将其用于连接和分组,任何帮助都将不胜感激 这是我的查询和输出 SELECT AttendanceDate,count(attendance)AS attendanceCount,AttOPt.Name AS AttendanceStatus,emp.Name AS MarkedBy FROM Attendance LEFT OUTER

您好,我已经创建了一个MS SQL查询,它正在生成完美的结果。但是我需要更改行和列的值。我在网上搜索并学习了PIVOT以改变方向。我已经创建了一些小的查询,但我无法将其用于连接和分组,任何帮助都将不胜感激

这是我的查询和输出

SELECT AttendanceDate,count(attendance)AS attendanceCount,AttOPt.Name AS AttendanceStatus,emp.Name AS MarkedBy FROM Attendance
LEFT OUTER JOIN AttendanceOption AttOPt
ON AttOPt.ID=Attendance
LEFT OUTER JOIN Employee emp
on MarkedBy=emp.Id
GROUP BY AttendanceDate,Attendance,MarkedBy,AttOPt.Name,emp.Name

我喜欢这样的输出:

AttendanceDate  Present Absent  Half Day    WithoutNotification MarkedBy
14-08-2013      11       0      0            0                  Anuj Koundal
30-08-2013      4        3      2            2                  Anuj Koundal
试试这个-

SELECT * 
FROM ( 
    SELECT  AttendanceDate
        ,   attendanceCount = COUNT(attendance) 
        ,   AttendanceStatus = AttOPt.name 
        ,   MarkedBy = emp.name 
    FROM Attendance
    LEFT JOIN AttendanceOption AttOPt ON AttOPt.id = Attendance
    LEFT JOIN Employee emp ON MarkedBy = emp.id
    GROUP BY
        AttendanceDate
    ,   Attendance
    ,   AttOPt.name
    ,   emp.name
) t
PIVOT 
(
    SUM(attendanceCount) 
    FOR AttendanceStatus IN ([Present], [Absent], [Half Day], [WithoutNotification])
) p
ORDER BY AttendanceDate DESC
更新:

-- variant #1

SELECT 
      AttendanceDate
    , MarkedBy 
    , [Present] = ISNULL([Present], 0)
    , [Absent] = ISNULL([Absent], 0)
    , [Half Day] = ISNULL([Half Day], 0)
    , [WithoutNotification] = ISNULL([WithoutNotification], 0)
FROM ( 
    ...
) t
PIVOT 
(
    ...
) p

-- variant #2

SELECT *
FROM ( 
    SELECT  
          AttendanceDate
        , attendanceCount = COUNT(attendance) 
        , AttendanceStatus = AttOPt.name 
        , MarkedBy = emp.name 
    FROM Attendance
    JOIN AttendanceOption AttOPt ON AttOPt.id = Attendance
    JOIN Employee emp ON MarkedBy = emp.id
    GROUP BY ALL
          AttendanceDate
        , Attendance
        , AttOPt.name
        , emp.name
) t
PIVOT 
(
    ...
) p
DECLARE @Columns NVARCHAR(MAX)
SELECT @Columns = STUFF((
    SELECT DISTINCT ', [' + a.name + ']'
    FROM dbo.Attendance t
    JOIN dbo.AttendanceOption a ON a.id = t.Attendance
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')

DECLARE @ColumnsNULLs NVARCHAR(MAX)
SELECT @ColumnsNULLs = STUFF((
    SELECT DISTINCT ', [' + a.name + '] = ISNULL([' + a.name + '], 0)'
    FROM dbo.Attendance t
    JOIN dbo.AttendanceOption a ON a.id = t.Attendance
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = '
SELECT AttendanceDate, ' + @ColumnsNULLs + ', MarkedBy
FROM ( 
    SELECT  AttendanceDate
        ,   attendanceCount = COUNT(attendance) 
        ,   AttendanceStatus = AttOPt.name 
        ,   MarkedBy = emp.name 
    FROM Attendance
    LEFT JOIN AttendanceOption AttOPt ON AttOPt.id = Attendance
    LEFT JOIN Employee emp ON MarkedBy = emp.id
    GROUP BY
        AttendanceDate
    ,   Attendance
    ,   AttOPt.name
    ,   emp.name
) t
PIVOT 
(
    SUM(attendanceCount) 
    FOR AttendanceStatus IN (' + @Columns + ')
) p
ORDER BY AttendanceDate DESC'

PRINT @SQL
EXEC sys.sp_executesql @SQL    
更新2:

-- variant #1

SELECT 
      AttendanceDate
    , MarkedBy 
    , [Present] = ISNULL([Present], 0)
    , [Absent] = ISNULL([Absent], 0)
    , [Half Day] = ISNULL([Half Day], 0)
    , [WithoutNotification] = ISNULL([WithoutNotification], 0)
FROM ( 
    ...
) t
PIVOT 
(
    ...
) p

-- variant #2

SELECT *
FROM ( 
    SELECT  
          AttendanceDate
        , attendanceCount = COUNT(attendance) 
        , AttendanceStatus = AttOPt.name 
        , MarkedBy = emp.name 
    FROM Attendance
    JOIN AttendanceOption AttOPt ON AttOPt.id = Attendance
    JOIN Employee emp ON MarkedBy = emp.id
    GROUP BY ALL
          AttendanceDate
        , Attendance
        , AttOPt.name
        , emp.name
) t
PIVOT 
(
    ...
) p
DECLARE @Columns NVARCHAR(MAX)
SELECT @Columns = STUFF((
    SELECT DISTINCT ', [' + a.name + ']'
    FROM dbo.Attendance t
    JOIN dbo.AttendanceOption a ON a.id = t.Attendance
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')

DECLARE @ColumnsNULLs NVARCHAR(MAX)
SELECT @ColumnsNULLs = STUFF((
    SELECT DISTINCT ', [' + a.name + '] = ISNULL([' + a.name + '], 0)'
    FROM dbo.Attendance t
    JOIN dbo.AttendanceOption a ON a.id = t.Attendance
    FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')

DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = '
SELECT AttendanceDate, ' + @ColumnsNULLs + ', MarkedBy
FROM ( 
    SELECT  AttendanceDate
        ,   attendanceCount = COUNT(attendance) 
        ,   AttendanceStatus = AttOPt.name 
        ,   MarkedBy = emp.name 
    FROM Attendance
    LEFT JOIN AttendanceOption AttOPt ON AttOPt.id = Attendance
    LEFT JOIN Employee emp ON MarkedBy = emp.id
    GROUP BY
        AttendanceDate
    ,   Attendance
    ,   AttOPt.name
    ,   emp.name
) t
PIVOT 
(
    SUM(attendanceCount) 
    FOR AttendanceStatus IN (' + @Columns + ')
) p
ORDER BY AttendanceDate DESC'

PRINT @SQL
EXEC sys.sp_executesql @SQL    
输出-

AttendanceDate          Absent      Half Day    Present     Without Notification MarkedBy
----------------------- ----------- ----------- ----------- -------------------- ---------------
2013-08-30 00:00:00.000 3           2           4           2                    Anuj Kaundal
2013-08-14 00:00:00.000 0           0           11          0                    Anuj Kaundal

参考:很好的解决方案,只剩下一点小东西,如何用0替换空值,目前没有。。专栏还有一个问题:我们可以让[出席]、[缺席]、[半天]、[不通知]这些专栏动态吗?最后一个问题:如何使用Order by?您在排序方面有任何问题吗?我需要按AttendanceDate描述分组