SQL: Mit Top-1 in UNION-Abfrage mit Sortierung nach
-
20-08-2019 - |
Frage
Ich habe eine Tabelle, wie unten
Rate Effective_Date
---- --------------
5.6 02/02/2009
5.8 05/01/2009
5.4 06/01/2009
5.8 12/01/2009
6.0 03/15/2009
Ich soll die Zimmer finden, die für das aktuelle Datum wirksam sind und danach. So die aktuelle effektive Rate zu erhalten, verwende ich
SELECT TOP 1 * from table
where effective_date < '05/05/2009'
order by effective date desc
für die Preise nach dem aktuellen Datum der Abfrage
SELECT * from table
where effective_date > '05/05/2009'
So kombinieren Sie diese beiden Ergebnis i verwenden, um eine Vereinigung wie
SELECT TOP 1 * from table
where effective_date < '05/05/2009'
order by effective date desc
UNION
SELECT * from table
where effective_date > '05/05/2009'
Das erwartete Ergebnis ist
Rate Effective Date
---- --------------
5.8 05/01/2009
5.4 06/01/2009
5.8 12/01/2009
6.0 03/15/2009
Aber ich bekomme das tatsächliche Ergebnis als
Rate Effective Date
---- --------------
5.6 02/02/2009
5.4 06/01/2009
5.8 12/01/2009
6.0 03/15/2009
Ich habe keine Ahnung, warum dies geschieht? Irgendwelche Vorschläge?
Lösung
Es funktioniert so:
select *
from (
select top 1 *
from table
where effective_date <= '05/05/2009'
order by effective_date desc
) as current_rate
union all
select *
from table
where effective_date > '05/05/2009'
Andere Tipps
Die Sortierung nach in einer select-Anweisung, den Teil einer Vereinigung ist, wird ignoriert. Daher Ihr TOP 1 ist ein willkürlichen Rekord (wahrscheinlich der erste Datensatz durch die gruppierten Schlüssel für die Tabelle) auswählen.
Order By ist ungültig, wenn es mit einer Union verwendet ...
Ich arbeitete einen Quickie und schmutzig Dingen mit Common Table Expression mit einem gewissen Rang und Case-Anweisung Tricks auf, um die Ergebnisse, die Sie für .. suchen
WITH CTE_RATES ( RATE, EFFECTIVE_DATE, CUR, SORT )
AS (
SELECT
Rate,
Effective_date,
CASE WHEN Effective_date > '5/5/2009' THEN 1
ELSE 0
END,
RANK() OVER (PARTITION BY
CASE WHEN EFFECTIVE_DATE > '5/5/2009' THEN 1
ELSE 0
END
ORDER BY EFFECTIVE_DATE DESC)
FROM TestTable
)
SELECT RATE, EFFECTIVE_DATE
FROM (
SELECT RATE, EFFECTIVE_DATE
FROM CTE_RATES
WHERE CUR = 0 AND SORT = 1
UNION ALL
SELECT RATE, EFFECTIVE_DATE
FROM CTE_RATES
WHERE CUR = 1
) AS QRY
ORDER BY EFFECTIVE_DATE
Um zu erklären, was passiert ist ...
Der CTE definiert die Rate, Datum, aktuelle und Sortier-Flags aus der Abfrage zurückgegeben ...
Die CASE trennt die Ergebnisse in denjenigen, die mit dem Datum der gewünschten Daten vor sind, und die, die nach dem Datum der gewünschten Daten sind .. Wir nutzen die Ergebnisse aus dem Gehäuse (CUR) in unserer Vereinigung, die Ergebnisse aus der partitionierten Liste zu ziehen. .
Der Rang () Funktion sortiert dann die Liste durch eine Partition auf den gleichen Kriterien zu schaffen, die CASE-Anweisung verwendet die Liste zu trennen .. dann sind wir durch den Zeitpunkt des Inkrafttretens bestellen Mode in absteigender Reihenfolge. Dies wird die „Vergangenheit“ Liste nehmen und machen es die meisten aktuellen „Vergangenheit“ -Eintrag Rang 1 ..
Dann in der Union Teil der Abfrage ..
Im oberen Teil sind wir den Rang und das Datum aus der „Vergangenheit“ -Liste (Aktuell = 0) und den ersten Eintrag in der „Vergangenheit“ Liste bekommen .. (sort = 1) .. das gibt 1 zurück Datensatz (oder 0, wenn es keine Aufzeichnungen gibt, die zum Datum der gewünschten Daten vor) sind ..
Dann wir Gewerkschaft, dass mit all dem Datensatz aus der „aktuellen“ Liste (Aktuell = 1)
Dann endlich .. nehmen wir die Ergebnisse der UNION .. und damit uns alle aktuellen Datensätze nach dem Wirksamwerden zu geben, und der „aktuelle“ bisherige Rekord.
Ich glaube, die obigen Abfragen 05.01.2009 werden ausschließlich unter Verwendung von