按 Null 字母顺序排序,然后按非 Null 排序

问题描述 投票:0回答:2

我有一个数据集,我试图首先按空开始日期值进行排序,然后按姓氏进行排序。然后是非空开始日期,也按姓氏:

  declare @t table
  (lastname varchar(100),
  firstname varchar(50),
  startdate date)

  insert into @t
  values('Smith', 'John', '01/01/2023'),
  ('Marshall', 'Tom', NULL),
  ('Thomas', 'Frank', '01/01/2022'),
  ('Schmidt', 'Mike', NULL),
  ('Carter', 'Gary', '03/01/2023'),
  ('Belle', 'Albert', NULL)

  LastName     FirstName       StartDate
 Smith         John               2023-01-01
 Marshall      Tom               NULL
 Thomas        Frank             2022-01-01
 Schmidt       Mike              NULL
 Carter        Gary             2023-03-01
 Belle         Albert           NULL

所需输出:

  LastName     FirstName        StartDate
   Belle         Albert           NULL
   Marshall       Tom             NULL
   Schmidt        Mike            NULL
   Carter        Gary             2023-03-01
   Smith         John             2023-01-01
   Thomas        Frank            2022-01-01     

我尝试过建立一个联盟:

  select * 
  into #nulls
  from @t
  where startdate is null
  order by lastname

  select * 
  into #nonnulls
  from @t
  where startdate is not null
  order by lastname

  select *
  from #nulls
  UNION
  select *
  from #nonnulls

我也尝试过使用按案例排序:

  select *
  from @t
  order by case when startdate is null then lastname 
                when startdate is not null then lastname end
sql-server case sql-order-by union
2个回答
1
投票

您只需要分别考虑这两个场景,而不是尝试将它们组合成一个

CASE
表达式。首先,优先考虑
startdate
null
的行,然后
lastname
排序:

ORDER BY CASE WHEN startdate IS NULL THEN 'a' ELSE 'z' END,
         lastname;

有效将所有没有开始日期的人合并到第一组(

a
),将有开始日期的人合并到第二组(
z
),然后在每个组中按姓氏排序。您可以在那里使用其他常量,例如
-1
/
0
1
/
2
-1
/
99


0
投票

ORDER BY CASE
的更有效版本是使用
UNION ALL
来组合两半,并使用排序列对其进行排序

SELECT *, 1 AS ordering
FROM @t
WHERE startdate IS NULL

UNION ALL

SELECT *, 2
FROM @t
WHERE startdate IS NOT NULL

ORDER BY
  ordering,
  lastname

这允许服务器使用合并串联而不是排序

© www.soinside.com 2019 - 2024. All rights reserved.