作者:TC维尼_748 | 来源:互联网 | 2022-12-08 13:27
我正在尝试将一些SQL移植到代码中,并且我注意到SQL Server的ORDER BY(和分区ORDER BY)在某些情况下似乎表现得有些不确定,但也许我只是没有看到这种模式.我正在使用Azure SQL数据库,它应该或多或少是SQL Server 2017,但有一些限制.
这里有些例子:
select * from (
values
('2014-01-01', NULL),
('2014-01-02', NULL),
(NULL, '2014-01-01 00:01:00'),
(NULL, '2014-01-01 23:59:59')
) AS temp (t, u)
order by isnull(t, u);
生成以下意外结果集,其中日期时间在同一天的日期之前,而较晚的日期时间在之前的日期之前:
t u
NULL 2014-01-01 23:59:59
NULL 2014-01-01 00:01:00
2014-01-01 NULL
2014-01-02 NULL
但是,如果我添加一些额外的行:
select * from (
values
('2014-01-01', NULL),
('2014-01-02', NULL),
(NULL, '2014-01-01 00:01:00'),
(NULL, '2014-01-01 23:59:59'),
(NULL, '2014-01-01 00:00:00'),
(NULL, '2014-01-02 00:00:00')
) AS temp (t, u)
order by isnull(t, u);
日期仍在日期时间之后,但现在日期时间依次为:
t u
NULL 2014-01-01 00:00:00
NULL 2014-01-01 00:01:00
NULL 2014-01-01 23:59:59
2014-01-01 NULL
NULL 2014-01-02 00:00:00
2014-01-02 NULL
使用分区产生类似的结果:
select
*,row_number() over (
partition BY g
ORDER BY isnull(t, u)
) rn
from (
values
(123, '2014-01-01', NULL),
(123, '2014-01-02', NULL),
(123, NULL, '2014-01-01 00:01:00'),
(123, NULL, '2014-01-01 23:59:59')
) AS temp (g, t, u);
select
*,row_number() over (
partition BY g
ORDER BY isnull(t, u)
) rn
from (
values
(123, '2014-01-01', NULL),
(123, '2014-01-02', NULL),
(123, NULL, '2014-01-01 00:01:00'),
(123, NULL, '2014-01-01 23:59:59'),
(123, NULL, '2014-01-01 00:00:00'),
(123, NULL, '2014-01-02 00:00:00')
) AS temp (g, t, u);
关于正在发生的事情或如何重现这种行为的任何指导将不胜感激.
1> Gordon Linof..:
如果您运行此查询:
select temp.*, isnull(t, u) from (values
('2014-01-01', NULL),
('2014-01-02', NULL),
(NULL, '2014-01-01 00:01:00'),
(NULL, '2014-01-01 23:59:59'),
(NULL, '2014-01-01 00:00:00'),
(NULL, '2014-01-02 00:00:00')
) temp (t, u)
order by isnull(t, u)
你会看到会发生什么.仅显示前10个字符.您可以在此rex测试仪中看到此信息.
isnull()
必须确定表达式的类型.它选择一个字符串,其长度是第一个参数.因此,结果非常有意义.这在文档中解释:
返回与check_expression相同的类型.
请注意,ANSI标准coalesce()
在类型检查方面做了更多工作,因此它返回您期望的内容.