鉴于以下数据:
Effective Date
--------------
2014-01-01
2015-01-01
2016-01-01
2017-01-01
2018-01-01
我希望按相对于(例如)2016-06-01
的日期排序,其中2016-06-01
以下的所有降序值都高于2016-06-01
以上的所有升序值。
Relative to date: 2016-06-01 the desired ordering is
Effective Date
--------------
2016-01-01
2015-01-01
2014-01-01
2017-01-01
2018-01-01
我想出达到所需顺序的最佳方法是:
CREATE TABLE #Dates
(
EffectiveDate DATETIME2
);
DECLARE @CurrentDate DATETIME2 = '2016-06-01';
DECLARE @MinDate DATETIME2 = '0001-01-01';
INSERT INTO #Dates (EffectiveDate) VALUES ('2014-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2015-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2016-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2017-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2018-01-01');
SELECT
*
FROM
#Dates
ORDER BY
CASE
WHEN #Dates.EffectiveDate < @CurrentDate
THEN DATEDIFF(DAY, #Dates.EffectiveDate, @CurrentDate)
ELSE
DATEDIFF(DAY, @CurrentDate, #Dates.EffectiveDate) - DATEDIFF(DAY, @CurrentDate, @MinDate)
END;
DROP TABLE #Dates;
有没有更好的方法来实现所需的排序?
答案 0 :(得分:3)
如果您有2012年及以上。
SELECT
*
FROM
#Dates
ORDER BY
IIF(#Dates.EffectiveDate <= @CurrentDate, 0,1) ASC
, ABS(DATEDIFF(day,#Dates.EffectiveDate, @CurrentDate)) ASC;
如果你有2008年:
SELECT
*
FROM
#Dates
ORDER BY
CASE
WHEN #Dates.EffectiveDate <= @CurrentDate THEN 0
ELSE 1 END ASC
, ABS(DATEDIFF(day,#Dates.EffectiveDate, @CurrentDate)) ASC;
答案 1 :(得分:2)
这是一种不同的方法。如果这符合您的需求,请告诉我。我使用的是表变量而不是临时表。
DECLARE @Dates TABLE
(
EffectiveDate DATETIME2
);
DECLARE @CurrentDate DATETIME2 = '2016-06-01';
INSERT INTO @Dates (EffectiveDate) VALUES ('2014-01-01');
INSERT INTO @Dates (EffectiveDate) VALUES ('2015-01-01');
INSERT INTO @Dates (EffectiveDate) VALUES ('2016-01-01');
INSERT INTO @Dates (EffectiveDate) VALUES ('2017-01-01');
INSERT INTO @Dates (EffectiveDate) VALUES ('2018-01-01');
SELECT *
FROM (SELECT TOP 1000000 *
FROM @Dates t1
WHERE EffectiveDate <= @CurrentDate
ORDER BY EffectiveDate DESC
UNION ALL
SELECT TOP 1000000 *
FROM @Dates t2
WHERE EffectiveDate NOT IN (
SELECT *
FROM @Dates
WHERE EffectiveDate <= @CurrentDate
)
ORDER BY EffectiveDate
) t
******* 修改 *******
如HABO所述,上述结果集不一定具有保证订单。以下编辑应该注意这一点。
SELECT *
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY EffectiveDate DESC) Sort
FROM @Dates t1
WHERE EffectiveDate <= @CurrentDate
UNION ALL
SELECT *
,(SELECT MAX(Sort)
FROM (SELECT *, ROW_NUMBER() OVER(ORDER BY EffectiveDate DESC) Sort
FROM @Dates t1
WHERE EffectiveDate <= @CurrentDate
) t2
)
+ ROW_NUMBER() OVER(ORDER BY EffectiveDate ASC) Sort
FROM @Dates t3
WHERE EffectiveDate NOT IN (SELECT *
FROM @Dates
WHERE EffectiveDate <= @CurrentDate)
) t
ORDER BY t.Sort
答案 2 :(得分:2)
对于这种特定情况,解决方案是直截了当的;在两个单独的列中拆分小于当前日期和大于当前日期,并相应地进行排序:
WITH CTE AS (
SELECT
EffectiveDate,
CASE WHEN EffectiveDate <= @CurrentDate THEN EffectiveDate END AS DL,
CASE WHEN EffectiveDate > @CurrentDate THEN EffectiveDate END AS DG
FROM #Dates
)
SELECT * FROM CTE
ORDER BY DL DESC, DG
结果:
EffectiveDate | DL | DG
====================+=====================+====================
2016-01-01 00:00:00 | 2016-01-01 00:00:00 | NULL
2015-01-01 00:00:00 | 2015-01-01 00:00:00 | NULL
2014-01-01 00:00:00 | 2014-01-01 00:00:00 | NULL
2017-01-01 00:00:00 | NULL | 2017-01-01 00:00:00
2018-01-01 00:00:00 | NULL | 2018-01-01 00:00:00
请注意,可以在不使用CTE的情况下编写查询。
答案 3 :(得分:1)
试试这个......
IF OBJECT_ID(N'tempdb..#Dates') IS NOT NULL
DROP TABLE #Dates
GO
CREATE TABLE #Dates
(
EffectiveDate DATETIME2
);
DECLARE @CurrentDate DATETIME2 = '2016-06-01';
DECLARE @MinDate DATETIME2 = '0001-01-01';
INSERT INTO #Dates (EffectiveDate) VALUES ('2014-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2015-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2016-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2017-01-01');
INSERT INTO #Dates (EffectiveDate) VALUES ('2018-01-01');
SELECT
EffectiveDate
FROM
(
SELECT
CASE
WHEN EffectiveDate <= @CurrentDate THEN 1
ELSE 2
END GroupId,
CASE
WHEN EffectiveDate <= @CurrentDate THEN EffectiveDate
ELSE NULL
END Group1,
CASE
WHEN EffectiveDate <= @CurrentDate THEN NULL
ELSE EffectiveDate
END Group2,
EffectiveDate
FROM
#Dates
)A
ORDER BY
GroupId,
Group1 DESC,
Group2 ASC