0在升序排序中排在最后。

10

我正在尝试从一张表中选择按价格、年份、名称和其他字段排序的产品列表...... 问题在于当升序排序时,我必须让零值排在最后。

我的代码是:

SELECT * FROM Product P 
ORDER BY  CASE WHEN @OrderBy='Date ASC' THEN Date  END ASC,
          CASE WHEN @OrderBy='Price ASC' THEN Price  END ASC,
          CASE WHEN @OrderBy='Title ASC' THEN Title  END ASC,
          CASE WHEN @OrderBy='' THEN Match END

这个方法可以正常工作,但是不要把零放在列表底部。 所以,我尝试进行转换(参见下一个代码),但是它给我报错:“附近的语法不正确”

SELECT * FROM Product P
ORDER BY CASE WHEN @OrderBy='Price ASC' THEN 

           (case A.Price WHEN  0 THEN 1 ELSE 0  END,A.Price )

END ASC

我感激任何帮助

6个回答

2

您可以通过两次价格排序来完成:

SELECT * FROM Product P 
ORDER BY  CASE WHEN @OrderBy='Date ASC' THEN Date  END ASC,
          CASE WHEN @OrderBy='Price ASC' THEN CASE WHEN Price = 0 THEN 1 ELSE 0 END ASC,
          CASE WHEN @OrderBy='Price ASC' THEN Price END ASC,
          CASE WHEN @OrderBy='Title ASC' THEN Title  END ASC,
          CASE WHEN @OrderBy='' THEN Match END

顺便提一下,当@orderBy不等于字符串时,case表达式的隐含值为null。 当排序列包含所有null时,它会有效地禁用该属性的排序。

我尝试运行你的代码,但是在第三行出现了错误:“关键字'ASC'附近的语法不正确”。为什么? - POIR
我忘记在第三个case表达式中加上END了。很抱歉,我在建议代码之前没有测试它! - Iain Samuel McLean Elder

1
我建议使用一个较大的虚拟价格:
ORDER BY CASE WHEN @OrderBy='Price ASC' THEN 99999999 ELSE A.Price END ASC

或者如果您的DBMS支持NULLS LAST:
ORDER BY CASE WHEN @OrderBy='Price ASC' THEN NULLIF(A.Price,0) END ASC NULLS LAST

遗憾的是,我的DBMS似乎不支持NULLS LAST。 - POIR
第一个建议怎么样? - Darkzaelus
是的,你说得对。第一个建议可以是一个选项,但我更喜欢我先前描述的方法,因为在我看来更加优雅。 - POIR

1
您可以尝试使用以下语法:

SELECT *,
    CASE WHEN @OrderBy = 'Price ASC' AND Price = 0 THEN 1 ELSE 0 END AS OrderPriceZeroLast
FROM Product P 
ORDER BY OrderPriceZeroLast,
    CASE WHEN @OrderBy = 'Date ASC' THEN Date END ASC,
    CASE WHEN @OrderBy = 'Price ASC' THEN Price END ASC,
    CASE WHEN @OrderBy = 'Title ASC' THEN Title END ASC,
    CASE WHEN @OrderBy = '' THEN Match END

这个答案与我的实际上是一样的。也许它更容易阅读,因为它使用列别名来描述零排序逻辑。 - Iain Samuel McLean Elder

1

我还无法添加评论。你的代码存在一个错误。

SELECT * FROM Product P
 ORDER BY CASE WHEN @OrderBy='Price ASC' THEN 
           (case A.Price WHEN  0 THEN 1 ELSE 0  END,A.Price )
END ASC

应该是类似这样的。
SELECT * 
FROM Product P
ORDER BY 
CASE 
  WHEN @OrderBy='Price ASC' 
  THEN 
    CASE A.Price 
      WHEN  0 
      THEN 1 
      ELSE 0  
      END  
END,
A.Price 

我忘记关闭case表达式了。谢谢Roman Sergeev的帮助,非常感激! - POIR

0

尝试使用以下方法将值为0的元素排在最后,当字段中存在0、1、2等数值时。它会将1、2等数值和0一起放在最后。

select * from Product 
order by 
case 
when OrderBy = 0 
    then -1 
else 0 
    end, 
OrderBy desc 

-Chirag


0
这可能看起来像一个小技巧,但你可以在结果集上动态创建一个新列。就像这样:
SELECT *,[可能包含零的列名] as foo WHERE /* 其余代码 */
然后你可以按 foo 进行 DESC 排序并按其余部分进行 ASC 排序。只需记住不向用户显示 foo,另外请注意,是的,你会在结果集中获得相同的列两次。你还必须使用 CASE 将所有非零值变成 1(或其他某个常量值)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接