使用基于派生列的条件(case)的sql数据排序

时间:2011-11-15 15:05:28

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

我想根据派生列的值对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

发现此错误:

  

Msg 145,Level 15,State 1,Line 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& amp;来尝试删除别名*,它会开始给出相同的选择明显错误只留下乘法部分

3 个答案:

答案 0 :(得分:2)

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

MY_TABLE:

id    value
1     1
2     2
3     1

现在,尝试按ID显示不同的value排序。它应该是什么?

value
1
2

value
2
1

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

现在,关于约定......也许其中一些就是你在这里发布的内容,但我会为你的代码提出以下建议:

避免对名称使用保留和SQL语言单词。这包括tablerankstatus

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

必须引用名称时使用带引号的标识符。如果您绝对必须违反上述两个建议之一,请使用标准的SQL Server引用标识符,即[]。如果你想引用别名,也可以使用它们(你不应该通常引用别名BTW)。这有助于避免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更加混乱,因为它使得看起来像别名列实际上是表中的一列。

答案 1 :(得分:1)

在字段名称周围使用'将它们转换为字符串。完全删除引号,或使用"代替。

答案 2 :(得分:1)

您的第二个示例最接近,因为它正确指定了列。但是,您不能按顺序对列进行别名。这可行:

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列。 / p>