【问题标题】:SQL - Insert NULL entry with Union then order by resultsSQL - 使用 Union 插入 NULL 条目,然后按结果排序
【发布时间】:2017-02-17 00:41:36
【问题描述】:

我正在尝试按结果的描述(不是 id)对结果列表进行排序,但我还需要插入另一个带有空 Id 和描述为“ALL”的结果。

为此,我使用UNION SELECT NULL, 'ALL'

这应该是一个非常简单的查询,但我不知道如何在查询对实际结果集进行排序之前插入“ALL”。

这是我目前所拥有的:

SELECT  *
FROM    [dbo].[HouseType]
WHERE   [TypeId] = COALESCE(@TypeId, [TypeId])
UNION SELECT NULL, 'ALL'
ORDER BY [TypeDesc]

我也尝试在结果排序之前调用 UNION SELECT,但看起来 SQL 不允许这样做。

UNION SELECT NULL, 'ALL'
SELECT * FROM
(
    SELECT      *
    FROM        [dbo].[HouseType]
    WHERE       [TypeId] = COALESCE(@TypeId, [TypeId])
    ORDER BY    [TypeDesc]
)types

基本上我想看到以下结果(有序):

  1. 全部
  2. 平房
  3. 分离
  4. 半独立式
  5. 露台

【问题讨论】:

  • 问题可能是通配符* 选择的列比您在UNION 中的显式选择中提到的要多
  • 插入表格。插入 ALL,然后从中选择并订购结果。
  • @GurV 在使用第二条语句时它给了我以下信息“ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效,除非 TOP 或 FOR XML 也是指定。”
  • 既然所有排序首先第一个应该工作。尝试实际的列名。

标签: sql sql-server tsql union


【解决方案1】:

尝试使用另一列:

SELECT  t.ID, t.description, 2 AS o
FROM    [dbo].[HouseType] AS t
WHERE   [TypeId] = COALESCE(@TypeId, [TypeId])

UNION ALL

SELECT NULL, 'ALL', 1 AS o
ORDER BY o, [TypeDesc]

这样ALL始终在原始查询的结果之前。

注意:正如评论中已经指出的,UNION 操作中使用的子查询的字段数量和类型之间必须匹配。

注意 2: 正如 @A ツ 在另一条评论中指出的那样,使用 UNION ALL 总是比 UNION 更可取,因此当您不必担心重复值时,请改用它。 p>

【讨论】:

  • 谢谢 Giorgos,您的回答与 Zohars 之间的表现如何?如果有的话,它看起来会非常简约。您是否建议在这种情况下使用 UNION ALL 而不是 UNION?
  • @Kendo 我认为使用这两个查询中的任何一个都不会对性能产生任何影响。你可以用你的实际数据测试两者,看看它们是如何比较的。 UNION ALL总是UNION 快,因为使用前者时 db 引擎不必查找重复项。
  • @GiorgosBetsos 恭喜获得 50K !!
  • @JohnCappelletti 谢谢!期待完成下一个 10Κ!
【解决方案2】:

在子查询中试一试

SELECT *
FROM(
    SELECT  *
    FROM    [dbo].[HouseType]
    WHERE   [TypeId] = COALESCE(@TypeId, [TypeId])
    UNION 
    SELECT NULL, 'ALL')
ORDER BY [TypeDesc]

【讨论】:

  • 有趣的是,唯一的答案就是一个。从问题中复制,b。错误和c。甚至不会编译是赞成的...
  • @ZoharPeled 当然这是问题的部分副本。我不是想改变 OP 的逻辑
【解决方案3】:
DECLARE @HouseType TABLE (HouseType VARCHAR(30))
INSERT INTO @HouseType
SELECT      HouseType 
    FROM        [dbo].[HouseType]
    WHERE       [TypeId] = COALESCE(@TypeId, [TypeId])
    ORDER BY    [TypeDesc]

INSERT INTO @HouseType
SELECT 'ALL'

SELECT HouseType FROM @HouseType ORDER BY HouseType 

【讨论】:

  • 在这种情况下创建临时表肯定是大材小用吗?
【解决方案4】:

我认为您正在寻找条件排序:

SELECT  *
FROM    [dbo].[HouseType]
WHERE   [TypeId] = COALESCE(@TypeId, [TypeId])
UNION ALL
SELECT NULL, 'ALL'
ORDER BY CASE WHEN [TypeDesc] = 'ALL' THEN 0 ELSE 1 END, [TypeDesc]

顺便说一句,我建议再次使用 * 并在选择列表中明确指定列名。
这始终是最佳实践,尤其是在使用 UNION 时 - 如果您从 HouseType 表中添加(或删除)列,此查询将引发错误。

【讨论】:

  • 谢谢 Zohar,我尝试了这个解决方案,但是当我运行它时,它抱怨“使用 UNION、INTERSECT 或 EXCEPT 运算符组合的所有查询必须在其目标列表中具有相同数量的表达式。”我错过了什么吗?该表仅包含 1) 一个 ID,2) 一个描述
  • 使用 * 或选择两列都没有关系,这个答案仍然会发生。
  • Opps,这是由于工会。如果是工会,一切都不会发生。编辑我的答案。
【解决方案5】:

使用按 TypeDesc 排序的 ROW_NUMBER 函数(+1 表示“ALL”之后)为每个 TypeDesc 分配一个 Row:

select 1 as [Row], 'All' as [TypeDesc]
union
SELECT ROW_NUMBER() OVER (ORDER BY TypeDesc) + 1 AS [Row], [TypeDesc]
    FROM        [dbo].[HouseType]
    WHERE       [TypeId] = COALESCE(@TypeId, [TypeId])
ORDER BY [Row]

【讨论】:

  • 嗨!如果您能提供一些有关您提供的代码的信息,那就太好了。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
  • 2018-04-13
相关资源
最近更新 更多