SQL 先排序,然后在 over 子句中分区
SQL first order, then partition in over clause
我有一个问题,我想对已排序的 table 进行分区。有什么办法可以做到吗?
我正在使用 SQL Server 2016。
输入Table:
|---------|-----------------|-----------|------------|
| prod | sortcolumn | type | value |
|---------|-----------------|-----------|------------|
| X | 1 | P | 12 |
| X | 2 | P | 23 |
| X | 3 | E | 34 |
| X | 4 | P | 45 |
| X | 5 | E | 56 |
| X | 6 | E | 67 |
| Y | 1 | P | 78 |
|---------|-----------------|-----------|------------|
期望输出
|---------|-----------------|-----------|------------|------------|
| prod | sortcolumn | type | value | rowNr |
|---------|-----------------|-----------|------------|------------|
| X | 1 | P | 12 | 1 |
| X | 2 | P | 23 | 2 |
| X | 3 | E | 34 | 1 |
| X | 4 | P | 45 | 1 |
| X | 5 | E | 56 | 1 |
| X | 6 | E | 67 | 2 |
| Y | 1 | P | 78 | 1 |
|---------|-----------------|-----------|------------|------------|
我到目前为止:
SELECT
table.*,
ROW_NUMBER() OVER(PARTITION BY table.prod, table.type ORDER BY table.sortColumn) rowNr
FROM table
但这不会重新开始第 4 行的行号,因为它是相同的产品和类型。
我如何根据排序标准重新启动每个产品以及每个类型更改,即使类型更改回之前已经存在的内容?这甚至可以使用 ROW_NUMBER 函数,还是我必须使用 LEAD、LAG 和 CASES(这可能会使它变得非常慢,对吧?)
谢谢!
这是一个缺口和孤岛问题。您可以使用以下查询:
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY prod ORDER BY sortcolumn)
-
ROW_NUMBER() OVER (PARTITION BY prod, type ORDER BY sortcolumn) AS grp
FROM mytable t
获得:
prod sortcolumn type value grp
----------------------------------------
X 1 P 12 0
X 2 P 23 0
X 3 E 34 2
X 4 P 45 1
X 5 E 56 3
X 6 E 67 3
Y 1 P 78 0
现在,字段grp
可用于分区:
;WITH IslandsCTE AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY prod ORDER BY sortcolumn)
-
ROW_NUMBER() OVER (PARTITION BY prod, type ORDER BY sortcolumn) AS grp
FROM mytable t
)
SELECT prod, sortcolumn, type, value,
ROW_NUMBER() OVER (PARTITION BY prod, type, grp ORDER BY sortcolumn) AS rowNr
FROM IslandsCTE
ORDER BY prod, sortcolumn
试试这个
select prod, sortcolumn, type, value, row_number() over (partition by prod, sortcolumn, type order by value) rowNr
from table_name
这是一个经典的 'islands' 问题,因为您需要找到与 prod
和 type
相关的记录的 'islands',但是 没有 将匹配 prod
和 type
.
的所有记录组合在一起
这是通常可以解决的一种方法。设置:
DECLARE @t TABLE (
prod varchar(1),
sortcolumn int,
type varchar(1),
value int
);
INSERT @t VALUES
('X', 1, 'P', 12),
('X', 2, 'P', 23),
('X', 3, 'E', 34),
('X', 4, 'P', 45),
('X', 5, 'E', 56),
('X', 6, 'E', 67),
('Y', 1, 'P', 78)
;
获取一些行号:
;WITH numbered AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY prod, type ORDER BY sortcolumn) as rnX,
ROW_NUMBER() OVER (PARTITION BY prod ORDER BY sortcolumn) as rn
FROM
@t
)
numbered
现在看起来像这样:
prod sortcolumn type value rnX rn
---- ----------- ---- ----------- -------------------- --------------------
X 1 P 12 1 1
X 2 P 23 2 2
X 3 E 34 1 3
X 4 P 45 3 4
X 5 E 56 2 5
X 6 E 67 3 6
Y 1 P 78 1 1
为什么这有用?好吧,看看 rnX
和 rn
之间的 差异 :
prod sortcolumn type value rnX rn rn - rnX
---- ----------- ---- ----------- -------------------- -------------------- --------------------
X 1 P 12 1 1 0
X 2 P 23 2 2 0
X 3 E 34 1 3 2
X 4 P 45 3 4 1
X 5 E 56 2 5 3
X 6 E 67 3 6 3
Y 1 P 78 1 1 0
如您所见,每个 'group' 共享一个 rn - rnX
值,这会从一组变为下一组。
所以现在如果我们按 prod
、type
、 和组编号 进行分区,那么 中的编号 :
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY prod, type, rn - rnX ORDER BY sortcolumn) rowNr
FROM
numbered
ORDER BY
prod, sortcolumn
我们完成了:
prod sortcolumn type value rnX rn rowNr
---- ----------- ---- ----------- -------------------- -------------------- --------------------
X 1 P 12 1 1 1
X 2 P 23 2 2 2
X 3 E 34 1 3 1
X 4 P 45 3 4 1
X 5 E 56 2 5 1
X 6 E 67 3 6 2
Y 1 P 78 1 1 1
我有一个问题,我想对已排序的 table 进行分区。有什么办法可以做到吗?
我正在使用 SQL Server 2016。
输入Table:
|---------|-----------------|-----------|------------|
| prod | sortcolumn | type | value |
|---------|-----------------|-----------|------------|
| X | 1 | P | 12 |
| X | 2 | P | 23 |
| X | 3 | E | 34 |
| X | 4 | P | 45 |
| X | 5 | E | 56 |
| X | 6 | E | 67 |
| Y | 1 | P | 78 |
|---------|-----------------|-----------|------------|
期望输出
|---------|-----------------|-----------|------------|------------|
| prod | sortcolumn | type | value | rowNr |
|---------|-----------------|-----------|------------|------------|
| X | 1 | P | 12 | 1 |
| X | 2 | P | 23 | 2 |
| X | 3 | E | 34 | 1 |
| X | 4 | P | 45 | 1 |
| X | 5 | E | 56 | 1 |
| X | 6 | E | 67 | 2 |
| Y | 1 | P | 78 | 1 |
|---------|-----------------|-----------|------------|------------|
我到目前为止:
SELECT
table.*,
ROW_NUMBER() OVER(PARTITION BY table.prod, table.type ORDER BY table.sortColumn) rowNr
FROM table
但这不会重新开始第 4 行的行号,因为它是相同的产品和类型。 我如何根据排序标准重新启动每个产品以及每个类型更改,即使类型更改回之前已经存在的内容?这甚至可以使用 ROW_NUMBER 函数,还是我必须使用 LEAD、LAG 和 CASES(这可能会使它变得非常慢,对吧?)
谢谢!
这是一个缺口和孤岛问题。您可以使用以下查询:
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY prod ORDER BY sortcolumn)
-
ROW_NUMBER() OVER (PARTITION BY prod, type ORDER BY sortcolumn) AS grp
FROM mytable t
获得:
prod sortcolumn type value grp
----------------------------------------
X 1 P 12 0
X 2 P 23 0
X 3 E 34 2
X 4 P 45 1
X 5 E 56 3
X 6 E 67 3
Y 1 P 78 0
现在,字段grp
可用于分区:
;WITH IslandsCTE AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY prod ORDER BY sortcolumn)
-
ROW_NUMBER() OVER (PARTITION BY prod, type ORDER BY sortcolumn) AS grp
FROM mytable t
)
SELECT prod, sortcolumn, type, value,
ROW_NUMBER() OVER (PARTITION BY prod, type, grp ORDER BY sortcolumn) AS rowNr
FROM IslandsCTE
ORDER BY prod, sortcolumn
试试这个
select prod, sortcolumn, type, value, row_number() over (partition by prod, sortcolumn, type order by value) rowNr
from table_name
这是一个经典的 'islands' 问题,因为您需要找到与 prod
和 type
相关的记录的 'islands',但是 没有 将匹配 prod
和 type
.
这是通常可以解决的一种方法。设置:
DECLARE @t TABLE (
prod varchar(1),
sortcolumn int,
type varchar(1),
value int
);
INSERT @t VALUES
('X', 1, 'P', 12),
('X', 2, 'P', 23),
('X', 3, 'E', 34),
('X', 4, 'P', 45),
('X', 5, 'E', 56),
('X', 6, 'E', 67),
('Y', 1, 'P', 78)
;
获取一些行号:
;WITH numbered AS (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY prod, type ORDER BY sortcolumn) as rnX,
ROW_NUMBER() OVER (PARTITION BY prod ORDER BY sortcolumn) as rn
FROM
@t
)
numbered
现在看起来像这样:
prod sortcolumn type value rnX rn
---- ----------- ---- ----------- -------------------- --------------------
X 1 P 12 1 1
X 2 P 23 2 2
X 3 E 34 1 3
X 4 P 45 3 4
X 5 E 56 2 5
X 6 E 67 3 6
Y 1 P 78 1 1
为什么这有用?好吧,看看 rnX
和 rn
之间的 差异 :
prod sortcolumn type value rnX rn rn - rnX
---- ----------- ---- ----------- -------------------- -------------------- --------------------
X 1 P 12 1 1 0
X 2 P 23 2 2 0
X 3 E 34 1 3 2
X 4 P 45 3 4 1
X 5 E 56 2 5 3
X 6 E 67 3 6 3
Y 1 P 78 1 1 0
如您所见,每个 'group' 共享一个 rn - rnX
值,这会从一组变为下一组。
所以现在如果我们按 prod
、type
、 和组编号 进行分区,那么 中的编号 :
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY prod, type, rn - rnX ORDER BY sortcolumn) rowNr
FROM
numbered
ORDER BY
prod, sortcolumn
我们完成了:
prod sortcolumn type value rnX rn rowNr
---- ----------- ---- ----------- -------------------- -------------------- --------------------
X 1 P 12 1 1 1
X 2 P 23 2 2 2
X 3 E 34 1 3 1
X 4 P 45 3 4 1
X 5 E 56 2 5 1
X 6 E 67 3 6 2
Y 1 P 78 1 1 1