构建数据透视表背后的步骤

时间:2014-07-16 04:20:09

标签: sql-server pivot-table

我对SQL有很好的理解(无论如何,我认为)。足够形成合理的查询并获得我想要的数据,尽管并不总是最好的格式。

我有以下查询;

DECLARE @StartDate DATE = '2014-07-01'
DECLARE @EndDate DATE = '2014-07-16'

SELECT Name, [Leave Type], SUM([Days Taken]) AS [Days Taken]
FROM(
    SELECT LR.idLeaveRequest, U.Name, LR.[start date], LR.[end date], SUM(DATEDIFF(DAY, LR.[start date], LR.[end date])) + 1 AS [Days Taken],
    L.LeaveType AS [Leave Type]
    FROM LeaveRequests LR
    INNER JOIN Users U ON U.idUser = LR.id_User
    INNER JOIN Leave L ON L.idLeave = LR.id_LeaveType
    WHERE @StartDate <= CAST([start date] AS DATE) AND @EndDate >= CAST([end date] AS DATE) AND id_Status = 3
    GROUP BY LR.idLeaveRequest, U.Name, LR.[start date], LR.[end date], L.LeaveType) AS Original
GROUP BY [Leave Type], Name

哪个获取数据,但它并不是最好的格式,因为“Joe”可能在Lieu有3天的年假和3天的离开,这意味着Joe有两行。理想情况下,它将是1行和2列。

认为我需要做一个PIVOT (MAX([Days Taken]) ON [Leave Type]),但我不确定是否可以从LeaveType表中动态获取列?此外,我不是100%肯定构建数据透视表的思考过程,我想如果有人能够解释从头开始(或从我目前所在的位置)开始可视化/构建表的最佳方法,我认为这对我来说还有很长的路要走,不需要再次寻求帮助。

(我不能使用除原始SQL之外的任何东西,因为这将进入一个程序,根据SQL查询的结果生成一个很好的报告)

表格数据

LeaveRequests  
idLeaveRequest int PK  
start date     DATE  
end date       DATE  
id_Status      int  
id_LeaveType   int  
id_User        int  

Leave  
idLeave int PK  
LeaveType varchar

User  
idUser int PK  
Name varchar

当前输出

Name | Leave Type | Days Taken  
Joe  | RDO        | 5  
Joe  | Annual     | 2  

所需输出

Name | Annual | RDO  
Joe  | 2      | 5  

2 个答案:

答案 0 :(得分:0)

使用以下查询以获得动态数据透视:

DECLARE @columns NVARCHAR(1000) = '',
        @sql NVARCHAR(MAX)

SELECT @Columns = STUFF((SELECT ',['+[Leave Type]+']'
                        FROM(
                            SELECT DISTINCT L.LeaveType AS [Leave Type]
                            FROM LeaveRequests LR
                            INNER JOIN Users U ON U.idUser = LR.id_User
                            INNER JOIN Leave L ON L.idLeave = LR.id_LeaveType
                            WHERE @StartDate <= CAST([start date] AS DATE) AND @EndDate >= CAST([end date] AS DATE) AND id_Status = 3
                            ) AS Original                        
                        FOR XML PATH('')),1,1,'')


SET @sql = 'DECLARE @StartDate DATE = ''2014-07-01''
            DECLARE @EndDate DATE = ''2014-07-16''

            SELECT * 
            FROM (
                SELECT Name, [Leave Type], SUM([Days Taken]) AS [Days Taken]
                FROM(
                    SELECT LR.idLeaveRequest, U.Name, LR.[start date], LR.[end date], SUM(DATEDIFF(DAY, LR.[start date], LR.[end date])) + 1 AS [Days Taken],
                    L.LeaveType AS [Leave Type]
                    FROM LeaveRequests LR
                    INNER JOIN Users U ON U.idUser = LR.id_User
                    INNER JOIN Leave L ON L.idLeave = LR.id_LeaveType
                    WHERE @StartDate <= CAST([start date] AS DATE) AND @EndDate >= CAST([end date] AS DATE) AND id_Status = 3
                    GROUP BY LR.idLeaveRequest, U.Name, LR.[start date], LR.[end date], L.LeaveType) AS Original
                GROUP BY [Leave Type], Name)p
            PIVOT (MAX([Days Taken]) FOR [Leave Type] IN ('+@columns+')Pvt'

EXECUTE(@sql)

答案 1 :(得分:0)

非动态的一般形式是:

DECLARE @StartDate DATE = '2014-07-01'
DECLARE @EndDate DATE = '2014-07-16'

SELECT Name, 
SUM(CASE WHEN [Leave Type] = 'RDO' THEN [Days Taken] ELSE 0 END) AS RDO,
SUM(CASE WHEN [Leave Type] = 'Annual' THEN [Days Taken] ELSE 0 END) AS Annual
FROM(
SELECT LR.idLeaveRequest, U.Name, LR.[start date], LR.[end date], 
SUM(DATEDIFF(DAY, LR.    [start date], LR.[end date])) + 1 AS [Days Taken],
L.LeaveType AS [Leave Type]
FROM LeaveRequests LR
INNER JOIN Users U ON U.idUser = LR.id_User
INNER JOIN Leave L ON L.idLeave = LR.id_LeaveType
WHERE @StartDate <= CAST([start date] AS DATE) AND 
@EndDate >= CAST([end date] AS DATE)     AND id_Status = 3
GROUP BY LR.idLeaveRequest, U.Name, LR.[start date], 
LR.[end date], L.LeaveType) AS Original
GROUP BY Name