更改时DENSE_RANK顺序断开

时间:2018-09-24 05:10:44

标签: sql sql-server tsql dense-rank

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

您可以在这里看到我所看到的许多错误之一:enter image description here

2 个答案:

答案 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,我们在gaps1,2行中有岛,分别有5IslandID中的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,46行中有孤岛,其中8,9IslandID,{{ 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中使用的每个分区