Эти два запроса основаны на предположении, которое Taco_value
всегда увеличивается со временем.
;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;
Альтернатива с меньшим количеством безумных оконных функций:
;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;
Примеры в SQLfiddle
Обновить
Для тех, кто следил, был спор о том, что произойдет, если Taco_value
когда-либо может повториться Если он может перейти от 1 к 2, а затем обратно к 1 для любого заданного Taco_ID
, запросы не будут работать. Вот решение для этого случая, даже если это не совсем техника пробелов и островков, о которой может мечтать кто-то вроде Ицик Бен-Гана, и даже если это не имеет отношения к сценарию ОП - это может быть отношение к будущему читателю. Это немного сложнее, и я также добавил дополнительную переменную - Taco_ID
которая есть только в одной Taco_value
.
Если вы хотите включить первую строку для любого идентификатора, значение которого не изменилось вообще во всем наборе:
;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;
Если вы хотите исключить эти строки, это немного сложнее, но все же незначительные изменения:
;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;
Обновленные примеры SQLfiddle
taco
, не имеет ничего общего с едой?