两个日期列按特殊逻辑排序
Posted
技术标签:
【中文标题】两个日期列按特殊逻辑排序【英文标题】:Two date column ordering according to special logic 【发布时间】:2021-10-20 15:38:02 【问题描述】:我需要一些帮助才能通过查询获得以下所需顺序,我已在下面硬编码所需顺序。如果日期列为空但优先考虑 [date] 其中不为空,我需要按列日期或创建日期排序,如下所示
Create Date | Date | Desired Order |
---|---|---|
2017-01-01 14:09:00.000 | NULL | 1 |
2017-01-01 14:10:03.000 | 2019-01-01 00:00:00.000 | 2 |
2017-01-01 14:10:04.000 | NULL | 3 |
2017-01-01 14:10:02.000 | 2020-01-01 00:00:00.000 | 4 |
2017-01-01 14:10:00.000 | 2021-01-01 00:00:00.000 | 5 |
drop table if exists #a
create table #a(
create_date datetime,
[date] datetime,
[desired_order] int,
primary key ([create_date])
);
insert into #a values('20170101 14:09:00.000', NULL, 1);
insert into #a values('20170101 14:10:00.000', '20210101',5);
insert into #a values('20170101 14:10:03.000', '20190101', 2);
insert into #a values('20170101 14:10:04.000', NULL, 3);
insert into #a values('20170101 14:10:02.000', '20200101', 4);
select * from #a order by desired_order
来自 cmets 的进一步解释:首先,我想按 create_date 排序,但任何出现乱序的日期值,即较新的日期出现在较早的行中,那么它需要是移动到结果集的末尾以及按日期排序的任何此类行。
接受答案后:我发现一组数据破坏了接受的解决方案:
insert into #a(create_date, [date]) values('20170101 14:09:00.000', NULL);
insert into #a(create_date, [date]) values('20170101 14:10:00.000', '20210101');
insert into #a(create_date, [date]) values('20170101 14:10:05.000', '20180101');
insert into #a(create_date, [date]) values('20170101 14:10:03.000', '20160101');
insert into #a(create_date, [date]) values('20170101 14:10:02.000', '20160205');
insert into #a(create_date, [date]) values('20170101 14:10:04.000', NULL);
insert into #a(create_date, [date]) values('20170101 14:10:01.000', '20200101');
insert into #a(create_date, [date]) values('20170101 14:10:06.000', '20230101');
insert into #a(create_date, [date]) values('20170101 14:10:07.000', '20170101');
由于某种原因,2017 年早于 2016 年,感谢您的帮助。
通过所有测试用例的解决方案:
;WITH cte1 AS (
SELECT
create_date,
[DATE],
ROW_NUMBER() OVER(ORDER BY CREATE_DATE) CN,
ROW_NUMBER() OVER(ORDER BY [DATE]) DN
FROM #a
)
select *
from
cte1
order by
case when [date] is null then CN else DN end,
CREATE_DATE
【问题讨论】:
ISNULL
/COALESCE
有什么问题?
order by coalesce([date],[create_date]) 将首先显示两个空日期行,这不是我想要的,请参阅上表。
你能解释一下为什么像 2019-01-01 00:00:00.000 这样的日期是第二个吗?
“如果日期列为空,我需要按日期列或创建日期排序,如下所示”,但以下数据不符合该要求。如果是这样,第 2 行就不是第 2 行,而是第 3 行。
他们复制粘贴了您评论的内容,这不是他们自己的话(我认为这在某些方面没有真正帮助)但我重新打开了@DaleK。
【参考方案1】:
这似乎是一个非常奇怪的要求。您可以使用min
解析函数来解决这个问题,以找出我们前面是否有更小的date
值。这是一个可能的解决方案,用 cmets 来解释逻辑:
with cte1 as (
select *
-- Find the smallest value between this row and the last row
, min([Date]) over (partition by case when [date] is not null then 1 else 0 end order by create_date desc rows between unbounded preceding and unbounded following) mindate
from #a
)
select create_date, [date]
-- Testing - uncomment to see how the logic works
--, desired_order, mindate
from cte1
-- If no date, always keep in the first section, and order by create_date
-- If there is a date, check whether this date is greater than the smallest date ahead of us, and if so move ahead
order by case when [date] is null then 0 else case when [date] > [mindate] then 1 else 0 end end, case when [date] > [mindate] then [date] else create_date end;
返回:
create_date | date |
---|---|
2017-01-01 14:09:00.000 | NULL |
2017-01-01 14:10:03.000 | 2019-01-01 00:00:00.000 |
2017-01-01 14:10:04.000 | NULL |
2017-01-01 14:10:02.000 | 2020-01-01 00:00:00.000 |
2017-01-01 14:10:00.000 | 2021-01-01 00:00:00.000 |
注意:由于您的示例数据非常简短,因此我无法确定此功能是否适用于所有边缘情况。
【讨论】:
你是对的,我发现一组数据打破了公认的逻辑,我已经更新了问题,感谢你的帮助。 嗨,很抱歉让您感到痛苦,但发现另一个问题,请参阅更新的“接受答案后”插入数据 @Alex 两件事,不断改变球门柱是一种非常糟糕的形式。您需要确保您提出的任何问题提前涵盖所有边缘情况。其次,我为您提供了一个很好的起点……与其要求我调整此查询以满足您的新数据,不如自己动手并理解逻辑以及如何调整它以满足您的新要求。您还缺少新数据集中所需的顺序。以上是关于两个日期列按特殊逻辑排序的主要内容,如果未能解决你的问题,请参考以下文章
excel分组,将A列按名称分组之后,B列再次内嵌分组,C列再次内嵌,怎么弄?很急!!!