2016-11-15 3 views
3

folgende Daten Gegeben:Sortieren nach allen Terminen unter einem bestimmten Wert absteigend dann mit allen Terminen über dem Wert aufsteigend

Effective Date 
-------------- 
    2014-01-01 
    2015-01-01 
    2016-01-01 
    2017-01-01 
    2018-01-01 

ich nach dem Datum relativ bestellen möge (zum Beispiel) 2016-06-01, in dem alle absteigend Werte unter 2016-06-01 kommen vor allen aufsteigenden Werten über 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 

Der beste Weg, ich bin gekommen, sich mit der gewünschten Anordnung zu erreichen ist:

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; 

Gibt es einen besseren Weg, um die gewünschte Reihenfolge zu erreichen?

Antwort

3

Wenn Sie 2012 und höher haben.

SELECT 
    * 
FROM 
    #Dates 
ORDER BY 
    IIF(#Dates.EffectiveDate <= @CurrentDate, 0,1) ASC 
    , ABS(DATEDIFF(day,#Dates.EffectiveDate, @CurrentDate)) ASC; 

Wenn Sie 2008:

SELECT 
    * 
FROM 
    #Dates 
ORDER BY 
    CASE 
     WHEN #Dates.EffectiveDate <= @CurrentDate THEN 0 
     ELSE 1 END ASC 
    , ABS(DATEDIFF(day,#Dates.EffectiveDate, @CurrentDate)) ASC; 
+0

'IIF()' wird ab 2012 funktionieren. – BJones

+1

Der Fall für 2008 hinzugefügt. – DVT

+0

Nur neugierig ... warum db spezifische Sprache verwenden? Fall funktioniert immer noch in beiden. Ist das wirklich viel schneller? – xQbert

2

Dies ist ein etwas anderer Ansatz. Lassen Sie mich wissen, ob dies Ihren Bedürfnissen entspricht. Ich habe eine Tabellenvariable anstelle einer temporären Tabelle verwendet.

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 

******* bearbeiten *******

Wie HABO erwähnt, das obige Ergebnis Satz würde nicht unbedingt eine garantierte Ordnung. Die folgende Änderung sollte dafür sorgen.

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 
+0

Wo bestellen Sie die Ergebnisse? Ohne eine ORDER BY-Klausel für das Endergebnis gibt es keine Garantie für die Bestellung. "UNION ALL" bietet keine Garantie für Ordnung. "TOP" stellt auch keine bestimmte Reihenfolge sicher, nur dass die Zeilen eine Teilmenge sind, die auf dem angegebenen 'ORDER BY' basiert. – HABO

+0

@HABO, stimmte ich das übersehen. Also wurde ich neugierig, wie ich es mit dem gleichen Ansatz zum Laufen bringen konnte. Es könnte hässlich sein, aber es scheint zu funktionieren. – BJones

2

Für diese spezielle Situation ist die Lösung gerade nach vorne; aufgeteilt weniger als Strom und größer als die aktuellen Termine in zwei getrennten Spalten und sortieren entsprechend:

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 

Ergebnis:

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 

Beachten Sie, dass es möglich ist, die Abfrage zu schreiben, ohne CTEs zu verwenden.

1

Try this ...

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 
Verwandte Themen