【问题标题】:Order a resultset by a specific requirement按特定要求订购结果集
【发布时间】:2018-03-04 00:42:18
【问题描述】:

我使用 SQL-Server 2008 遇到了这个问题,最好用一个例子来解释:

假设我有这个号码 3776。我想按以下顺序排列我的结果列表:

3775
3777
3774
3778
3773
3779
...

换句话说,基于 3776 在两个方向上都尽可能接近,加上 AND 减去。

例如这只会给我肯定的命令:

where FIELDNAME > 3776
order by FIELDNAME asc

我怎样才能得到所需的结果?

【问题讨论】:

  • 当两个数字接近于 3776 时,是否有一些关于必须先显示哪个数字的标准?大的还是小的?

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


【解决方案1】:

我认为你可以使用它。我认为 order by 子句对于获得所有记录的相同序列很重要(您可以决定使用 X ASC 或 X DESC ):

WITH Y AS (SELECT 3775 AS X UNION ALL SELECT 3776 UNION ALL SELECT 3774 
           UNION ALL SELECT 3773 UNION ALL SELECT 3778 UNION ALL SELECT 3779 
           UNION ALL SELECT 3777)
SELECT X
FROM Y 
WHERE X<>3776
ORDER BY ABS(3776-X), X ASC;

输出:

3775
3777
3774
3778
3773
3779

如果你使用

WITH Y AS (SELECT 3775 AS X UNION ALL SELECT 3776 UNION ALL SELECT 3774 
           UNION ALL SELECT 3773 UNION ALL SELECT 3778 UNION ALL SELECT 3779 
           UNION ALL SELECT 3777)
SELECT X
FROM Y 
WHERE X<>3776
ORDER BY ABS(3776-X)

您可以获得以下内容。重要的是要记住,如果您不指定 order by 子句,则记录的顺序是不确定的。因此,如果您仅指定 ORDER BY ABS(3776-X),则无法确定是更大或更小的数字(与起始数字具有相同的 ABS 差异)首先出现。

3775
3777
3774
3778
3779
3773

【讨论】:

    【解决方案2】:
    with t(col) as (
        select 3775 union all 
        select 3777  union all 
        select 3774  union all 
        select 3778  union all 
        select 3773  union all 
        select 3779
        )
     select *  from t
     order by abs(col - 3776), col
    

    【讨论】:

      【解决方案3】:
      DECLARE @startnum int = 1;
      DECLARE @endnum int = 21;
      DECLARE @point int = 11;
      
      
      WITH seq AS 
      (
          SELECT @startnum AS num
          UNION ALL
          SELECT num + 1 FROM seq WHERE num + 1 <= @endnum
      ),
      cte AS
      (
          SELECT num, abs(@point - num) [shift]
              FROM seq 
      )
      SELECT num
          FROM cte
          ORDER BY [shift], num;
      

      输出:

      num
      -----------
      11
      10
      12
      9
      13
      8
      14
      7
      15
      6
      16
      5
      17
      4
      18
      3
      19
      2
      20
      1
      21
      

      【讨论】:

        【解决方案4】:

        您可以按 3776 与字段值之间的绝对差值对查询进行排序:

        SELECT   *
        FROM     mytable
        ORDER BY ABS(3776 - fieldname)
        

        【讨论】:

        • @Murenik 你不应该在订单子句中添加 , 字段名吗?
        • @etsa 会优先考虑小于3776 的值而不是大于它的值。你可以,但这似乎不是 OP 想要实现的目标。
        • @Murenik,据我所知,这是他问的......(理论上你也应该添加 WHERE 3776...... :-)
        • @etsa 的要求是“n 换句话说,基于 3776 在两个方向上尽可能接近,加上 AND 减去。” OP 给出了order by FIELDNAME 作为他当前的尝试,但没有产生正确的值
        猜你喜欢
        • 2019-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-31
        • 2015-05-30
        • 2016-06-13
        相关资源
        最近更新 更多