【问题标题】:Order by integer with blank fields at the bottom按整数排序,底部有空白字段
【发布时间】:2009-06-03 13:06:04
【问题描述】:

我们目前正在重写我们的 CMS,我们希望我们的客户能够使用“位置”字段对表格中的项目进行重新排序。因此,如果他们将一个项目标记为位置 1,它将位于顶部,然后位于其下方的位置 2,依此类推。

问题是我们不希望他们每次都必须填写一个职位,只有当他们想要重新订购某些东西时,职位字段通常会是空白的。所以你可能有以下...

汽车 - 1

自行车 - 2

房子

电脑

这会导致问题,因为如果您使用以下 SQL...

SELECT ProductName FROM Products ORDER BY Position DESC;

所有空白的都到顶部,而不是底部。

可以使用 SQL 语句将它们按正确的顺序排列吗?

【问题讨论】:

  • 大卫 B 有正确的答案,按两个表达式排序。第一个表达式有几个替代方案,“技巧”是将所有非 NULL 值组合在一起。如果 'Position' 是数字,您可以轻松地为所有非 NULL 值生成 0 以将它们组合在一起... ORDER BY Position-Position DESC, Position DESC

标签: sql sql-server sql-server-2008


【解决方案1】:
SELECT ProductName
FROM Products
ORDER BY
  CASE WHEN Position is null THEN 1 ELSE 0 END,
  Position

如果您想在底部保持空值的同时按位置降序排序,则可以这样做:

ORDER BY
  CASE WHEN Position is null THEN 1 ELSE 0 END,
  Position desc

如果您想要一致的排序(您可能需要分页),请在末尾添加 ProductName 或 ProductID 以打破未定位产品之间的所有联系。

ORDER BY
  CASE WHEN Position is null THEN 1 ELSE 0 END,
  Position,
  ProductID

【讨论】:

  • +1 @David:我认为这是正确的答案(按两个表达式而不是 1 排序)。我唯一看到的是您错过了 DESC 关键字(来自 OP 问题)。
  • @David:你没有错过 DESC 关键字,我弄错了。 (我无法编辑我以前的评论。(D'Oh!)我在 OP 问题中得到了示例 SQL 的 DESC 关键字,但这不是 OP 想要的。如果我绝对坚持使用 DESC 关键字(而且我除了我可能喜欢算术表达式和不必要的混淆之外,没有其他理由... ORDER BY Position-Position DESC, -1*Position DESC
  • 应该有一个红色的小按钮,里面有一个 x,可以让你删除自己的评论。
【解决方案2】:
SELECT  ProductName
FROM    Products
ORDER BY
        COALESCE(position, (SELECT MAX(position) + 1 FROM Products))

或者,您可以使用:

SELECT  *
FROM    (
        SELECT  ProductName
        FROM    Products
        WHERE   position IS NOT NULL
        ORDER BY
                position
        ) q
UNION ALL
SELECT  ProductName
FROM    Products
WHERE   position IS NULL

这会更有效率,因为第一个子查询将使用position 上的索引进行排序。

【讨论】:

  • 他想按 asc 排序,而不是 desc。而不是 -1,它应该是(从产品中选择 max(position)+1),并且 ProductName 应该是按标准的第二个顺序。
【解决方案3】:

仅在必要时使用 NULL

您可以通过将“未设置”行默认为整数最大值来轻松消除空值的使用以及由此产生的排序问题:

  • 更新产品 SET Position=2147483647 WHERE Position IS NULL
  • 将列设置为NOT NULL,添加默认值2147483647
  • 按预期使用您的 ORDER BY
  • 在您的应用或负载查询中,禁止显示 2147483647 的任何值

这是一个示例加载:

SELECT 
    ProductName
        ,CASE
             WHEN Position=2147483647 THEN NULL  --or cast this as a varchar and use 'N/A'
             ELSE Position
         END
    FROM ...

如果你必须使用空值,这样做:

SELECT
    ProductName
        ,Position
    FROM Test
    ORDER BY COALESCE(Position,2147483647)

【讨论】:

  • 嗯。我会在 ORDER BY 中使用 NULL 和 ISNULL。 NULL 比任意值更好,而 COALESCE 更慢
  • 如果每一行都有一个值,您不必使用 ISNULL 或 COALESCE,这将是最快的。
【解决方案4】:

这应该为您完成这项工作。

CREATE TABLE [dbo].[Test](
    [Position] [int] NULL,
    [Title] [varchar](15) NULL
) 
GO

INSERT INTO Test Values(1, 'P1')
INSERT INTO Test Values(2, 'P2')
INSERT INTO Test Values(NULL, 'P3')
INSERT INTO Test Values(NULL, 'P4')
INSERT INTO Test Values(NULL, 'P5')
GO

SELECT Title + ' - ' +  CASE  
    WHEN POSITION IS NULL THEN ''
    ELSE CAST(Position AS CHAR(3))
    END
FROM Test
ORDER BY CASE WHEN Position is null THEN 1 ELSE 0 END

【讨论】:

    猜你喜欢
    • 2018-08-25
    • 2020-04-24
    • 2014-11-22
    • 1970-01-01
    • 2016-08-14
    • 2017-07-08
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多