微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 SQL Server 上使用变量作为数据透视列

如何解决如何在 SQL Server 上使用变量作为数据透视列

我在使带有数据透视列的表在 MS sql Server 上更具动态性时遇到问题。

我有一个查询从当前年份的五周时间段和前一年的五周时间段中检索数据,因此列 CUR_YR 和 PREV_YR 是来自数据透视子句的数据。这是我的查询

DECLARE @TODAY DATE
SET @TODAY= CAST(GETDATE() AS DATE)
DECLARE @PREV_YR INT,@CUR_YR INT
SET @CUR_YR = YEAR(@TODAY)
SET @PREV_YR = @CUR_YR-1

SELECT * FROM (
    SELECT BUS,DET,[STR],COALESCE(@PREV_YR,0) AS PREV_YR,COALESCE(@CUR_YR,0) AS CUR_YR FROM (
        SELECT YR,BUS,count(ORD_ID_SE) as ORDS FROM (<SUBQUERY>) )AS T
PIVOT(
    SUM(ORDS)
    FOR YR IN (
            @PREV_YR,@CUR_YR)
) AS pivot_table
)AS F

当我手动将 FOR YR IN() 子句中的枢轴列设置为 2020 和 2021 时,查询有效,但由于我需要这些列是动态的(也就是让它们随着时间的推移而改变,所以接下来年份是 2021 和 2022)我使用变量@PREV_YR 和@CUR_YR,如代码所示。但是,这会导致错误“'@PREV_YR' 附近的语法不正确。”。

解决办法吗?也许用不同的方式来满足 IN() 子句中的两年。

感谢您的帮助。

解决方法

这是 PIVOT 功能的一个已知限制。您的 IN 列表中必须有一组预定义的列。它们不能动态改变。因此,为了做到这一点,您需要利用动态 SQL 根据您的输入值更改结果集。

有很多关于如何执行此操作的指南,但我将举例说明如何将其应用于脚本(添加了一些小的重新格式化)。为了运行它,我确实纠正了两个问题。 1.为您的子查询添加别名subquery_alias 2.将GROUP BY子句添加到您的聚合查询

DECLARE @TODAY DATE = CAST(GETDATE() AS DATE); 
DECLARE @CUR_YR INT = YEAR(@TODAY); 
DECLARE @PREV_YR INT = @CUR_YR-1; 
DECLARE @Sql nvarchar(max) =
N'SELECT    
    * 
FROM 
    (SELECT 
        BUS,DET,[STR],COALESCE(' + QUOTENAME(CAST(@PREV_YR AS nvarchar(10))) + N',0) AS PREV_YR,COALESCE(' + QUOTENAME(CAST(@CUR_YR AS nvarchar(10))) + N',0) AS CUR_YR 
    FROM 
        (SELECT 
            YR,BUS,COUNT(ORD_ID_SE) AS ORDS 
        FROM 
            (<SUBQUERY>) AS subquery_alias
        GROUP BY 
            YR,[STR]) AS T
PIVOT(SUM(ORDS) FOR YR IN (' + QUOTENAME(CAST(@PREV_YR AS nvarchar(10))) + N',' + QUOTENAME(CAST(@CUR_YR AS nvarchar(10))) + N')) AS pivot_table) AS F'; 

EXEC sys.sp_executesql @Sql; 

话虽如此,在这种情况下,您将数据透视表的输出分别重新别名为 PREV_YRCUR_YR。所以你真的不需要动态列名,如果你只打算以这种方式使用两个不同的变量,那么使用 SUM(CASE WHEN....END) 方法旋转它更有意义。像这样:

DECLARE @TODAY DATE = CAST(GETDATE() AS DATE); 
DECLARE @CUR_YR INT = YEAR(@TODAY); 
DECLARE @PREV_YR INT = @CUR_YR-1; 
SELECT  
    BUS,SUM(CASE WHEN YR = @PREV_YR THEN 1 ELSE 0 END) AS PREV_YR,SUM(CASE WHEN YR = @CUR_YR THEN 1 ELSE 0 END) AS CUR_YR
FROM 
    (<SUBQUERY>) AS subquery_alias
GROUP BY 
    BUS,[STR];

这样做可以完全避免动态 SQL 和更复杂的数据透视查询。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?