【问题标题】:Steps behind building a Pivot Table构建数据透视表的步骤
【发布时间】:2014-07-16 04:20:08
【问题描述】:

我对 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”可能有 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  

【问题讨论】:

  • 请为您的表、示例行和预期输出添加创建表语句。那么,帮助你就很容易了。
  • @BoratSagdiyev 现在还有更多帮助吗?
  • 您能否列出所有可能的休假类型,因为我们需要明确定义每一列。

标签: sql-server pivot-table


【解决方案1】:

非动态的一般形式是:

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

【讨论】:

  • 可以做动态吗?我不需要它说0,它可以为null。
  • 另一个答案是动态答案。去吧。
【解决方案2】:

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

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)

【讨论】:

  • 它给出了以下错误:必须声明标量变量“@StartDate”。
  • @FizzBu​​zz。我改变了我的答案。请再次检查。
  • 谢谢。我可能应该提到,这是通过 C# SqlDataAdapter 和 SqlCommand 运行的......它似乎不喜欢将上面的整个答案放入一个字符串中。可以修复吗?还是我应该让自己让它静态化?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 2017-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多