我正在使用最新版本的 SQL Server 并遇到以下問題。鑒于下表,要求非常簡單,就是洗掉每個_category磁區中具有_value = 0. 在此背景關系中的尾隨意味著,當記錄按順序放置時,應洗掉串列末尾的_date任何系列或連續記錄塊。磁區中具有某些非零值的后續記錄的記錄應該保留_value = 0。_value = 0
create table #x (_id int identity, _category int, _date date, _value int)
insert into #x values (1, '2022-10-01', 12)
insert into #x values (1, '2022-10-03', 0)
insert into #x values (1, '2022-10-04', 10)
insert into #x values (1, '2022-10-06', 11)
insert into #x values (1, '2022-10-07', 10)
insert into #x values (2, '2022-10-01', 1)
insert into #x values (2, '2022-10-02', 0)
insert into #x values (2, '2022-10-05', 19)
insert into #x values (2, '2022-10-10', 18)
insert into #x values (2, '2022-10-12', 0)
insert into #x values (2, '2022-10-13', 0)
insert into #x values (2, '2022-10-15', 0)
insert into #x values (3, '2022-10-02', 10)
insert into #x values (3, '2022-10-03', 0)
insert into #x values (3, '2022-10-05', 0)
insert into #x values (3, '2022-10-06', 12)
insert into #x values (3, '2022-10-08', 0)
我看到了幾種方法。蠻力方法是按日期順序通過游標運行記錄,并獲取任何記錄的 ID_value = 0并查看它是否存在,直到類別發生變化。如果可以在查詢中執行,我會盡量避免使用 T-SQL。
為此,我想我可以應用一些間隙和孤島技巧并使用視窗函式做一些事情。我覺得可能有一種方法可以利用last_value()這一點,但到目前為止,我只看到它在識別具有標準的磁區方面很有用,而不是幫助我獲取要洗掉的記錄的 ID。
期望的結果是洗掉記錄 10、11、12 和 17。
感謝任何幫助。
uj5u.com熱心網友回復:
我不確定您的要求是否需要差距和孤島方法。簡單的存在邏輯應該有效。
SELECT _id, _catrgory, _date, _value
FROM #x x1
WHERE _value <> 0 OR
EXISTS (
SELECT 1
FROM #x x2
WHERE x2._category = x1._category AND
x2._date > x1._date AND
x2._value <> 0
);
uj5u.com熱心網友回復:
假設所有_values 都大于或等于,0您可以MAX()在 updatable 中使用視窗函式CTE:
WITH cte AS (
SELECT *,
MAX(_value) OVER (
PARTITION BY _category
ORDER BY _date
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) max
FROM #x
)
DELETE FROM cte
WHERE max = 0;
如果有負數_values 使用MAX(ABS(_value))而不是MAX(_value).
請參閱演示。
uj5u.com熱心網友回復:
使用公用表運算式,您可以使用:
WITH CTE_NumberedRows AS (
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY _category ORDER BY _date)
FROM #x
),
CTE_Keepers AS (
SELECT _category, rnLastKeeper = MAX(rn)
FROM CTE_NumberedRows
WHERE _value <> 0
GROUP BY _category
)
DELETE NR
FROM CTE_NumberedRows NR
LEFT JOIN CTE_Keepers K
ON K._category = NR._category
WHERE NR.rn > ISNULL(K.rnLastKeeper, 0)
有關作業演示,請參閱此 db<>fiddle 。
編輯:我原來的帖子沒有處理全零的邊緣情況。上面已更正此問題,并進行了一些命名調整。(原件仍然可以在這里找到。
Tim Biegeleisen 的帖子可能是更簡單的方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/536654.html
