Hai truy vấn này dựa trên giả định Taco_value
luôn tăng theo thời gian.
;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;
Một thay thế với sự điên rồ chức năng cửa sổ ít hơn:
;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;
Ví dụ tại SQLfiddle
Cập nhật
Đối với những người theo dõi, đã có sự tranh cãi về những gì sẽ xảy ra nếu Taco_value
có thể lặp lại. Nếu nó có thể đi từ 1 đến 2 và sau đó trở về 1 cho bất kỳ Taco_ID
, các truy vấn sẽ không hoạt động. Đây là một giải pháp cho trường hợp đó, ngay cả khi đó không phải là kỹ thuật của những khoảng trống và hòn đảo mà một người như Itzik Ben-Gan có thể mơ được, và ngay cả khi nó không phù hợp với kịch bản của OP - nó có thể có liên quan đến một độc giả tương lai. Nó phức tạp hơn một chút và tôi cũng đã thêm một biến bổ sung - một biến Taco_ID
chỉ có một Taco_value
.
Nếu bạn muốn bao gồm hàng đầu tiên cho bất kỳ ID nào có giá trị không thay đổi trong toàn bộ:
;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;
Nếu bạn muốn loại trừ các hàng đó, nó phức tạp hơn một chút, nhưng vẫn có những thay đổi nhỏ:
;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;
Các ví dụ SQLfiddle được cập nhật
taco
không có gì để làm với thực phẩm?