SQL 错误 - Windows 函数只能出现在 SELECT 或 ORDER BY 子句中

Posted

技术标签:

【中文标题】SQL 错误 - Windows 函数只能出现在 SELECT 或 ORDER BY 子句中【英文标题】:SQL ERROR - Windows functions can only appear in SELECT or ORDER BY clauses 【发布时间】:2018-02-21 15:43:52 【问题描述】:

我对 SQL 比较陌生,正在尝试找出我在帖子标题中出现错误的原因。 (我觉得跟LAG函数有关系?)

这是我要执行的代码:

ALTER TABLE [MyDatabase].[dbo].[MyTable]
ADD Calc_Column AS CAST
(
    CASE WHEN [Variable_X]  = LAG([Variable_X],1,0) OVER (Order By FileDate)
          AND [Variable_Y] != LAG([Variable_Y],1,0) OVER (Order By FileDate) 
          AND [ACTUAL START DATE] != 0
          AND [FileDate] >= [ACTUAL START DATE]
         THEN 1
         ELSE 0
    END AS N
)
GO

【问题讨论】:

错误信息的哪一部分不清楚? 请给我们一个样本数据和预期结果。谢谢。 报错中说窗口函数只能在SELECTORDER BY中使用,所以不能在CASE语句中使用 ***.com/questions/14111321/… @mitchmitch24 。 . .您可以为此功能使用视图。 【参考方案1】:

错误信息非常明确:您可以使用窗口函数 (lag),在这种情况下,除了 select 子句或 order by 子句之外的任何地方。 计算列只能引用来自函数或当前行的值,不能在其声明中直接包含 select 语句。 但它可以使用用户定义的标量函数来计算,所以如果你真的想计算使用窗口函数计算的列,你必须使用用户定义的函数来完成。我试图为你制作一个示例函数,但由于你没有共享你的表的 DDL,我不得不做出假设和猜测,而且我无法测试它 - 所以它可能不完全适合。但是,它应该足以显示总体思路,并且您应该能够根据需要对其进行修改。

CREATE FUNCTION dbo.CalculateMyColumn
(
    -- Assuming an int identity column with ascending order
    @PrimaryKeyColumn int 
)
Returns Bit
AS
BEGIN
    DECLARE @ReturnValue bit

    ;WITH cte AS
    (
        SELECT Variable_X, 
               LAG([Variable_X],1,0) OVER (Order By FileDate) As Prev_Variable_X,
               Variable_Y, 
               LAG([Variable_Y],1,0) OVER (Order By FileDate) As Prev_Variable_Y,
               [ACTUAL START DATE], 
               [FileDate],
               PrimaryKeyColumn
        FROM TableName
        WHERE PrimaryKeyColumn <= @PrimaryKeyColumn
    )

    SELECT @ReturnValue = 
            CASE WHEN Variable_X = Prev_Variable_X
                 AND Variable_Y != Prev_Variable_Y
                 AND [ACTUAL START DATE] != 0
                 AND [FileDate] >= [ACTUAL START DATE]
            THEN 1
            ELSE 0
            END
    FROM cte
    WHERE PrimaryKeyColumn = @PrimaryKeyColumn

END

然后您可以更改表格以添加计算列:

ALTER TABLE [MyDatabase].[dbo].[MyTable]
ADD Calc_Column AS dbo.CalculateMyColumn(PrimaryKeyColumn)
GO

请注意,此函数依赖于主键列是升序的 int 标识列。

【讨论】:

干得好——这就是我要提出的建议,但有一个重要的警告:计算列的 T-SQL 标量 UDF、检查约束或任何与此相关的东西,都是性能杀手。它们的存在导致优化器选择串行执行计划,即使并行计划更好。请注意 Eric Darling 的这篇精彩文章:计算列中的标量函数是一个坏主意的另一个原因 (brentozar.com/archive/2016/01/…)。 @AlanBurstein 感谢您的链接!我知道标量 UDF 通常意味着性能不佳,但我不知道有任何其他方法可以让计算列依赖于内置函数和当前行数据之外的任何内容。也许 Gordon 提出观点的建议是一个更好的解决方案。

以上是关于SQL 错误 - Windows 函数只能出现在 SELECT 或 ORDER BY 子句中的主要内容,如果未能解决你的问题,请参考以下文章

windows2012R2安装SQL2005详情!

SQL登陆出现错误,用SQL身份登陆没问题,用windows身份登陆就出现下面的错误。求解!!!

Sql server - 窗口函数只能出现在 SELECT 或 ORDER BY 子句中

SQL Server 2012 安装出现错误:在运行 Windows Installer 文件时遇到错误。

我可以让 SQL*Plus 在函数编译失败时退出并出现错误吗?

为啥我的SQL 2005用Windows身份验证登陆的时候出现18456错误