【问题标题】:order by sql data using condtions (case) based on derived columns使用基于派生列的条件(大小写)按 sql 数据排序
【发布时间】:2011-12-29 14:51:54
【问题描述】:

我想设置一个条件来根据派生列的值对 SQL 数据进行排序,如下所示:

SELECT DISTINCT sp.ID
    , sp.Status
    , sp.Rank
    , sp.Price
    , sp.SalePrice
    , sp.Width
    , sp.Height
    , sp.QOH
    , (sp.SalePrice*sp.QOH) As 'sp.Value'
    , (sp.Price*sp.QOH) As 'sp.StandardValue'
FROM table 
WHERE -- Conditions
ORDER BY
  CASE WHEN 'sp.SalePrice' > 0 THEN 'sp.Value'  END DESC,
  CASE WHEN 'sp.SalePrice' = 0 THEN 'sp.StandardValue'  END DESC

出现此错误:

消息 145,第 15 级,状态 1,第 1 行
如果指定了 SELECT DISTINCT,则 ORDER BY 项必须出现在选择列表中。

如果我尝试

ORDER BY
  CASE WHEN sp.SalePrice > 0 THEN (sp.SalePrice*sp.QOH) As "sp.Value"  END DESC,
  CASE WHEN sp.SalePrice = 0 THEN (sp.Price*sp.QOH) As sp.StandardValue" END DESC

给出错误:

关键字“As”附近的语法不正确。

如果我尝试从 cluase 的顺序中删除别名 * 并且只保留乘法部分,它就会开始给出相同的选择不同的错误

【问题讨论】:

  • WHERE 条件中是否有任何子查询?我没有看到DISTINCT。您是否可能在某些时候包含了 DISTINCT 却忘记将其包含在您上面的问题中?
  • 我忘了在上面的代码中添加 DISTINCT,现在完成了

标签: sql sql-server sql-server-2008 select sql-order-by


【解决方案1】:

在字段名称周围使用' 会将它们转换为字符串。要么完全删除引号,要么改用"

【讨论】:

  • ' 替换为"sp.Value"results 按子句的顺序给出错误消息207,列名无效
  • 您不能在 SQL Server 的 order/where 子句中使用别名。你必须复制完整的推导函数,所以它是ORDER BY ... THEN sp.SalePrice*sp.QOH ...
  • 我已经更新了问题以包含您的建议,它也给出了错误
  • 您可以在ORDER BY 中使用别名,因为逻辑上这是在SELECT 之后处理的
【解决方案2】:

我将在下面添加一些关于一般约定的建议,但至于主要问题,请考虑您要使用此示例做什么:

我的表:

id    value
1     1
2     2
3     1

现在,尝试显示不同的 value 按 id 排序。应该是哪个?

value
1
2

value
2
1

所以,您要求 SQL Server 做一些不可能或至少不清楚的事情。

现在,关于约定...也许其中一些就是您在此处发布的方式,但我会为您的代码提出以下建议:

避免在名称中使用保留字和 SQL 语言字。这将包括tablerankstatus

避免在名称中使用特殊字符。这将包括sp.value。当然,您可以使用带引号的标识符来执行此操作,但是即使 SQL 支持,某些前端等可能不支持它们,并且在大多数情况下使用它们并不会真正购买任何东西。

当您必须引用名称时,请使用带引号的标识符。如果您绝对必须违反上述两个建议之一,请使用 SQL Server 的标准引用标识符,即[]。如果你想引用别名,也可以使用它们(顺便说一句,你通常不必引用别名)。这有助于避免 Mark B 指出的问题。

您的CASE 语句最好写成一个排序列。此外,在大多数情况下,您应该包含 ELSE 以避免未处理的情况。只要您在任何涉及的列中都不能有 NULL 或负值,这里可能不需要这样做。

CASE
    WHEN sp.SalePrice > 0 THEN (sp.SalePrice*sp.QOH)
    WHEN sp.SalePrice = 0 THEN (sp.Price*sp.QOH)
END

我个人会避免将表别名(看起来您不小心遗漏在查询中)作为列别名的一部分。它使 IMO 更加混乱,因为它使别名列看起来实际上是表中的一列。

【讨论】:

  • 但是假设这个值是一个别名
  • 为什么应该是2、1? id 的值为 1,那么为什么不先出现呢?您是否看到 DISTINCT 是如何做到的,因此您最终可能会按列排序,该列可能具有与实际显示的每一行相关联的多个值?
  • Tom,感谢您的详细回答,table 等关键字仅用于演示目的。你提到的情况确实给出了错误incorrect syntax near the keyword 'CASE',即使我把CASE sp.SalePrice 错误仍然存​​在
  • 对不起...我忘了你不能在ORDER BY 中使用别名。我会更正那个代码。您之前没有收到错误,因为 SQL 将“sp.Value”视为实际字符串“sp.value”。
  • @TomH。 - 你可以ORDER BY中使用别名
【解决方案3】:

您的第二个示例最接近,因为它正确指定了列。但是,您不能在 order by 中对列进行别名。这会起作用:

ORDER BY
  CASE WHEN sp.SalePrice > 0 THEN sp.SalePrice*sp.QOH END DESC,
  CASE WHEN sp.SalePrice = 0 THEN sp.Price*sp.QOH END DESC

或者只使用您在结果集中定义的别名:

ORDER BY
  CASE WHEN sp.SalePrice > 0 THEN [sp.Value] END DESC,
  CASE WHEN sp.SalePrice = 0 THEN [sp.StandardValue] END DESC

注意括号 []....这是定义列名所必需的,因为您在别名中使用了点分名称...否则 sp.Value 将被视为 sp 表中的 Value 列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2016-09-25
    相关资源
    最近更新 更多