【问题标题】:Order by with case statement fails only when using a parameter with error ORDER BY items must appear in the select list仅当使用带有错误的参数 ORDER BY 项必须出现在选择列表中时,Order by with case 语句才会失败
【发布时间】:2013-06-03 19:40:19
【问题描述】:

我有一个存储过程,其中包含 3 个由联合连接的查询。这行得通。它目前有一个按值设置的顺序,如下所示:

    ORDER BY [CategoryTypeID], [SortOrder], [Name]

我想让这个动态,所以我尝试使用这样的 case 语句:

    ORDER BY CASE WHEN @sort = 0 then [CategoryTypeID] ELSE [SortOrder] end

但是,当我这样做时,sql 会抱怨如果语句包含 union...等,则按项目排序必须出现在选择列表中。

但是,如果我更改以上内容以避免使用参数:

ORDER BY CASE WHEN 0 = 0 then [CategoryTypeID] ELSE [SortOrder] end

这行得通。为什么当我使用一个参数而实际上并没有按顺序使用该参数时会不高兴?我什至尝试在 select 语句中包含参数,但它仍然给了我同样的错误。

我也尝试过 case @sort when 1 etc,但得到了相同的结果。我确实在我的存储过程中声明了参数 - @sort int = 0

这是 MSSQL 2012 快递

编辑 - 为了更加清晰

 ORDER BY CASE WHEN @sort = 0 then [SortOrder] ELSE [CategoryTypeID] end

ORDER BY CASE WHEN @sort = 0 then [CategoryTypeID] ELSE [CategoryTypeID] end

这两个语句都失败,并出现“必须出现在选择列表中”错误。而且我并没有尝试同时使用这两个语句。只是将它们作为示例,列本身似乎不是问题。它使用的参数似乎是一个问题,即使参数本身没有被选择或排序。

【问题讨论】:

  • 您的 SELECT 列表中有什么......?您实际上需要选择这个。
  • 因为在第二种情况下永远不会到达ELSE,所以 SQL Server 就好像它不存在一样。尝试将其更改为WHEN 1 = 0SortOrder 在您的 SELECT 列表中吗?如果没有,为什么不呢?
  • 对不起,如果我不清楚 - 如果您查看第一行示例代码,那就可以了。意思是,所有 3 列都在选择中。因此,永远不会达到 else 并不重要。我可以交换 else 中的哪一列并得到相同的结果。出于某种原因,它只是不喜欢正在使用的参数

标签: sql-server parameters sql-order-by


【解决方案1】:

CASE WHEN 0 = 0 then [CategoryTypeID] ELSE [SortOrder] end在编译时解析并简化为CategoryTypeID

你可以的

WITH T
     AS (SELECT [CategoryTypeID],
                [SortOrder]
         FROM   T1
         UNION
         SELECT [CategoryTypeID],
                [SortOrder]
         FROM   T2)
SELECT *
FROM   T
ORDER  BY CASE
            WHEN @sort = 0 THEN [CategoryTypeID]
            ELSE [SortOrder]
          END 

或者

SELECT [CategoryTypeID],
       [SortOrder],
       CASE
         WHEN @sort = 0 THEN [CategoryTypeID]
         ELSE [SortOrder]
       END AS S
FROM   T1
UNION
SELECT [CategoryTypeID],
       [SortOrder],
       CASE
         WHEN @sort = 0 THEN [CategoryTypeID]
         ELSE [SortOrder]
       END AS S
FROM   T2
ORDER  BY S 

【讨论】:

  • 联合中有两个相同的选择有什么意义?
  • @merk - 它们不相同,因为它们来自不同的表。如果您展示了更多原始查询,则可以使其更具相关性。
  • 啊抱歉,我错过了 T1 与 T2 位。
【解决方案2】:

AFAICT SQL Server 不支持这样的语句,如错误所示。您可以使用 IF 构造根据参数进行不同的排序。

IF @sort=0
    SELECT ... ORDER BY CategoryTypeID;
ELSE
    SELECT ... ORDER BY SortOrder;

【讨论】:

  • 拥有 50 个代表后,您可以评论其他人的答案。 +1 因为如果存在索引来支持排序,则划分为两个查询可能会比捕获所有查询提供更好的计划。我不同意whatever you do DO NOT USE WITH EVER 的说法。你的依据是什么?
  • 此外,Martin Smiths 版本选择了一个额外的列以便对其进行排序。 IF 构造更多地键入(当然是复制/粘贴),但至少它不会选择您不需要的额外列。 OTOH,如果您更改/更新查询,您将不得不重新输入(当然是复制/粘贴)到 ELSE 部分。
  • 我回答中的第二个版本只是因为他们提到“我什至尝试在选择语句中包含参数”以表明这是可能的。仍在等待您反对WITH 的理由
  • 个人经历。绝对糟糕的表现。如果同事不知道这一点,问我为什么他们的查询需要 11(十一)小时才能运行。他们正在使用 WITH。更改为派生表,查询只需几秒钟即可运行。那是在 SQL Server 2008 上。 WITH 子句中的表每次在查询中需要时都会重新计算……它是一个(表)表达式,而不是派生表。
  • 派生表和公用表表达式的代数相同。如果您在从一个切换到另一个时有不同的计划,那么肯定是发生了其他事情(例如参数嗅探)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多