grp
列应代表由GroupId, RouteId
划分并按LengthStart
排序的块,其中,如果locationId保持不变,则在遍历这些块时grp
是相同。序列中的中断会创建一个新的grp
+---------+----------+--------------+------------+-------------+------+
| GROUPID | ROUTEID | LENGTHSTART | LENGTHEND | LOCATIONID | GRP |
+---------+----------+--------------+------------+-------------+------+
| 1 | A | 0 | 1 | 1 | 1 |
| 1 | A | 1 | 2 | 1 | 1 |
| 1 | A | 2 | 3 | 2 | 2 |
| 1 | A | 3 | 4 | 1 | 3 |
| 2 | A | 2 | 3 | 2 | 4 |
| 1 | B | 2 | 3 | 2 | 5 |
| 1 | A | 4 | 5 | 1 | 3 |
+---------+----------+--------------+------------+-------------+------+
我对这个问题的搜索使我找到了这个解决方案:DENSE_RANK according to particular order
我尝试进行grp
计算:
SELECT *, ROW_NUMBER() OVER (ORDER BY GroupId, RouteId, LengthStart) - ROW_NUMBER() OVER (PARTITION BY GroupId, RouteId, LocationId ORDER BY GroupId, RouteId, LengthStart) AS grp
FROM mytable
我试图采用该解决方案,以便可以进行更多级别的分区,并且可以在真正的基本用例中工作(例如上面展示的那种,但是在复杂的情况下会失败)。
我不太清楚为什么要减去两个row_number()以及它是如何工作的,但是在简单的示例中它确实工作得很好。
我尝试了其他使用LAG
的方法,但是只是不了解如何理解逻辑并应用它。
在这里摆弄着更复杂的场景:
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=3704dfe8583b0dd020b189184d149cb7
答案 0 :(得分:1)
这似乎是一个空白问题,您对解决方案有误解。
在这种情况下,grp
列本身并不能识别出间隙或孤岛,它只是为您提供了您需要识别的 额外 信息他们。
对于您而言,(locationId, grp)
的实现方式将形成新的“ sub_group”标识符。
我也将稍微更改您的查询,以使其易于了解正在发生的事情...
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY GroupID, RouteID ORDER BY LengthStart)
- ROW_NUMBER() OVER (PARTITION BY GroupId, RouteId, LocationId ORDER BY LengthStart) AS grp
FROM
mytable
ORDER BY
GroupId, RouteId, LengthStart
这更清楚地表明,在计算间隙和孤岛(子组)时,不同的GroupID, RouteID
彼此之间没有任何关联[strong> )。
然后我可以显示一个简化的示例...
LocationID, Start, SetRowNum, LocRowNum, Difference, GroupID
1 000 1 1 0 (1,0)
1 100 2 2 0 (1,0)
2 200 3 1 2 (2,2)
2 300 4 2 2 (2,2)
1 400 5 3 2 (1,2)
2 500 6 3 3 (2,3)
3 600 7 1 6 (3,6)
2 700 8 4 4 (2,4)
2 800 9 5 4 (2,4)
为每个island
分别计算一个LocationID
。
gap
只是任何其他LocationID
的任何行。
“窍门”是在每个岛中,两个行号一起增加。通过将两者加在一起,差异保持不变。区别在于island_id
。
然后,在间隔期间,第一个行号增加,这样,当我们到达下一个岛时,两个行号之间的差异增加,从而为该island_id
提供新的LocationID
**。
请记住,在计算island_id
的{{1}}时,我们将 所有其他位置 视为位置1的岛之间的location_1
。
对于位置1,我们在gaps
和1,2
行中有岛,分别有5
和IslandID
中的0
。
2
对于位置2,我们在 LocationID, Start, SetRowNum, LocRowNum, Difference, GROUP_ID
1 000 1 1 0 (1,0)
1 100 2 2 0 (1,0)
GAP
1 400 5 3 2 (1,2)
,3,4
和6
行中有孤岛,其中8,9
,IslandID
,{{ 1}}。
2
对于位置3,我们在3
行的4
中有 LocationID, Start, SetRowNum, LocRowNum, Difference
GAP
2 200 3 1 2 (2,2)
2 300 4 2 2 (2,2)
GAP
2 500 6 3 3 (2,3)
GAP
2 700 8 4 4 (2,4)
2 800 9 5 4 (2,4)
的岛屿。
7
总而言之,所有岛屿都有不同的ID。
但是Location1和Location2都具有IslandID = 2的岛屿。
IslandID
答案 1 :(得分:0)
通过更改over子句的参数将产生不同的结果。请注意,您无需按顺序重复用于分区的列。此技术的概念是计算一个常用值(在<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
列中),该常用值通常用于随后的计算中,例如;步骤数,成本或最小/最大等。
grp
输出两个row_number计算结果非常有用,这样您就可以了解其工作原理:
SELECT
*
, ROW_NUMBER() OVER (ORDER BY GroupId, RouteId, LengthStart)
- ROW_NUMBER() OVER (PARTITION BY GroupId, RouteId ORDER BY LengthStart ) AS grp
FROM mytable
ORDER BY
GroupId
, RouteId
, LengthStart
Id GroupId RouteId LengthStart LengthEnd LocationId rn1 rn2 grp
--------- --------- --------- ------------- ----------- ------------ ----- ----- -----
2651246 3 AAA 0.0000000 0.0920000 1884268 1 1 0
2651247 3 AAA 0.0920000 0.5800000 1855305 2 2 0
2651248 3 AAA 0.5800000 1.3610000 1884268 3 3 0
2651249 3 AAA 1.3610000 1.6170000 1884268 4 4 0
2651250 3 AAA 1.6170000 2.3750000 1884268 5 5 0
2681493 3 BBB 0.0000000 1.5600000 1864963 6 1 5
2681494 3 BBB 1.5600000 2.7100000 1864963 7 2 5
2681495 3 BBB 2.7100000 3.3900000 1864963 8 3 5
2954915 3 CCC 0.0000000 0.0500000 1883382 9 1 8
2954916 3 CCC 0.0500000 0.1400000 1846300 10 2 8
…
列从1开始,并一直递增。第二个rn列从每个分区的1重新开始,但是由于它也以相同的顺序递增1,因此当您从rn1
中减去rn2
时,您会得到{{1} }用于rn2中使用的每个分区