Diese beiden Abfragen beruhen auf der Annahme, dass Taco_value
sie mit der Zeit immer größer werden.
;WITH x AS
(
SELECT Taco_ID, Taco_date,
dr = ROW_NUMBER() OVER (PARTITION BY Taco_ID, Taco_Value ORDER BY Taco_date),
qr = ROW_NUMBER() OVER (PARTITION BY Taco_ID ORDER BY Taco_date)
FROM dbo.Taco
), y AS
(
SELECT Taco_ID, Taco_date,
rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID, dr ORDER BY qr DESC)
FROM x WHERE dr = 1
)
SELECT Taco_ID, Taco_date
FROM y
WHERE rn = 1;
Eine Alternative mit weniger Fensterfunktionswahnsinn:
;WITH x AS
(
SELECT Taco_ID, Taco_value, Taco_date = MIN(Taco_date)
FROM dbo.Taco
GROUP BY Taco_ID, Taco_value
), y AS
(
SELECT Taco_ID, Taco_date,
rn = ROW_NUMBER() OVER (PARTITION BY Taco_ID ORDER BY Taco_date DESC)
FROM x
)
SELECT Taco_ID, Taco_date FROM y WHERE rn = 1;
Beispiele bei SQLfiddle
Aktualisieren
Für diejenigen, die den Überblick behielten, gab es Streit darüber, was passieren würde, wenn sich Taco_value
dies jemals wiederholen könnte. Wenn es von 1 auf 2 und dann wieder auf 1 gehen könnte, Taco_ID
funktionieren die Abfragen nicht. Hier ist eine Lösung für diesen Fall, auch wenn es nicht ganz die Technik von Gaps & Islands ist, die sich jemand wie Itzik Ben-Gan ausdenken kann, und selbst wenn sie für das OP-Szenario nicht relevant ist - es kann sein relevant für einen zukünftigen Leser. Es ist etwas komplexer, und ich habe auch eine zusätzliche Variable hinzugefügt - eine Taco_ID
, die immer nur eine hat Taco_value
.
Wenn Sie die erste Zeile für eine ID einfügen möchten, bei der sich der Wert im gesamten Satz überhaupt nicht geändert hat:
;WITH x AS
(
SELECT *, rn = ROW_NUMBER() OVER
(PARTITION BY Taco_ID ORDER BY Taco_date DESC)
FROM dbo.Taco
), rest AS (SELECT * FROM x WHERE rn > 1)
SELECT
main.Taco_ID,
Taco_date = MIN(CASE
WHEN main.Taco_value = rest.Taco_value
THEN rest.Taco_date ELSE main.Taco_date
END)
FROM x AS main LEFT OUTER JOIN rest
ON main.Taco_ID = rest.Taco_ID AND rest.rn > 1
WHERE main.rn = 1
AND NOT EXISTS
(
SELECT 1 FROM rest AS rest2
WHERE Taco_ID = rest.Taco_ID
AND rn < rest.rn
AND Taco_value <> rest.Taco_value
)
GROUP BY main.Taco_ID;
Wenn Sie diese Zeilen ausschließen möchten, ist dies etwas komplexer, es werden jedoch noch kleinere Änderungen vorgenommen:
;WITH x AS
(
SELECT *, rn = ROW_NUMBER() OVER
(PARTITION BY Taco_ID ORDER BY Taco_date DESC)
FROM dbo.Taco
), rest AS (SELECT * FROM x WHERE rn > 1)
SELECT
main.Taco_ID,
Taco_date = MIN(
CASE
WHEN main.Taco_value = rest.Taco_value
THEN rest.Taco_date ELSE main.Taco_date
END)
FROM x AS main INNER JOIN rest -- ***** change this to INNER JOIN *****
ON main.Taco_ID = rest.Taco_ID AND rest.rn > 1
WHERE main.rn = 1
AND NOT EXISTS
(
SELECT 1 FROM rest AS rest2
WHERE Taco_ID = rest.Taco_ID
AND rn < rest.rn
AND Taco_value <> rest.Taco_value
)
AND EXISTS -- ***** add this EXISTS clause *****
(
SELECT 1 FROM rest AS rest2
WHERE Taco_ID = rest.Taco_ID
AND Taco_value <> rest.Taco_value
)
GROUP BY main.Taco_ID;
Aktualisierte SQLfiddle-Beispiele
taco
hat nichts mit dem Essen zu tun?