是否可以撰寫一個每次磁區值更改時進行磁區的視窗函式?
例如:
create table test (id int, i int);
insert into test values (1, 1), (2, 0),(3, 0),(4, 1),(5, 1),(6, 1),(7, 0),(8, 0),(9, 1);
select
id,
i,
row_number() over (partition by i order by id asc) rn
from
test
order by
id asc;
會給我以下結果:
id i rn
----------
1 1 1
2 0 1
3 0 2
4 1 2
5 1 3
6 1 4
7 0 3
8 0 4
9 1 5
但是,我希望能夠在i根據我的排序順序更改的值時再次重新啟動計數器,無論它是否已經出現。
例如,想要的結果是這樣的:
id i rn
----------
1 1 1
2 0 1
3 0 2
4 1 1
5 1 2
6 1 3
7 0 1
8 0 2
9 1 1
相同的原則適用于其他視窗函式,例如累積和。
我真的不想為此回圈,而且我無法找到正確的視窗函式。
謝謝
uj5u.com熱心網友回復:
這個問題是一個缺口和孤島問題。我從這個問題中得出了我對這個問題的解決方案:
在值更改時重置行號,但在磁區中重復值
我的查詢如下所示:
with cte as (
SELECT id, i,
ROW_NUMBER() OVER (PARTITION BY i order by id) rn1
FROM test
)
SELECT id, i,
ROW_NUMBER() OVER (PARTITION BY CAST((id - rn1) as CHAR(100)) || CAST(i as CHAR(100)) ORDER BY id) rn
FROM cte
ORDER BY
id
我擴展了您的資料集以驗證答案。我在 Tim Biegeleisen 的回答中使用了相同的概念。我得到 i 的行號,然后從 id 中減去它。這些差異應該導致具有相同 i 的每個 id 編號具有相同的值,直到 i 再次切換。我在 8,0 時遇到了一個問題,row_number 為 4(導致差異為 4)和 9,1 和 row_number 為 5(也導致差異為 4)。為了解決這種情況,我將差異轉換為一個字串并連接 I,形成一個唯一的 id,我們可以對其進行磁區。
您可以在此 dbfiddle 中查看:https ://www.db-fiddle.com/f/hnGUTZGLvRQ5JoSCHozAhs/0
uj5u.com熱心網友回復:
您可以通過添加包含前一個i(使用lag(i))的列來實作這一點,然后保持“翻轉”(當前 i <> 前一個 i)的總次數。具有相同翻轉次數的行屬于同一組。
with u as
(select id, i, lag(i) over (order by id) as previousi
from test),
v as
(select id,
i,
sum(case when i = previousi then 0 else 1 end)
over (order by id rows unbounded preceding) as flips
from u)
select id, i, row_number() over (partition by flips order by id) as rn
from v
小提琴
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/393000.html
標籤:sql sql-server 查询语句
上一篇:按序列號和按標志分組的SUM值
下一篇:洗掉日期不是最小值的行
