假设我们有一个列为";事件":
events
A
b
c
d
e
A
b
c
d
A
f
我想在这样的拆分上获得WindowGroups或只是一个带有row_number((的新列
events
A
b
c
d
e
f
g
----- split here ---
A
b
c
d
----- split here ---
A
f
所以我想把所有的行都放在";A";在";事件";列添加到一个组中。怎么做?我觉得这可以用Window函数来完成。
最后,我自己得到了一个解决方案。这是:
import org.apache.spark.sql.expressions.Window
val windowIndex = Window.partitionBy().orderBy("time")
val result = eventWithTime
.withColumn("groupId",
when($"events" === "A", row_number over windowIndex).otherwise(null))
.withColumn("groupId", last("groupId", ignoreNulls = true) over windowIndex)
.filter($"groupId".isNotNull)
(我使用"时间"列只是为了像示例中那样对事件进行排序(
这里的想法是找到所有";事件";用";A";并用唯一的id标记它们。我使用CCD_ 1和CCD_。(也许使用monotonically_increasing_id
会更好,但我有很多数据,并且对monotonically_increasing_id
的正确工作有一些假设(。之后,我使用了具有相同窗口的函数last
。这里重要的是将ignoreNulls设置为";真";。这样,所有的null都将在当前行之前用第一个非null值填充。然后我只是把第一行放在第一行之前;A";因为它们仍然是null。
示例:
- 在进行任何操作之前
events
A
b
c
d
e
A
b
c
d
A
f
- 将唯一id分配给所有"A";s(否则为空(
events | groupId
A | 1
b | null
c | null
d | null
e | null
A | 2
b | null
c | null
d | null
A | 3
f | null
- 使用最后一个非null值填充null
events | groupId
A | 1
b | 1
c | 1
d | 1
e | 1
A | 2
b | 2
c | 2
d | 2
A | 3
f | 3
现在,我们可以通过groupId只使用groupBy
或partitionBy
,并执行我们想要的操作。
CREATE TABLE #tbl(event nvarchar(5))
insert into #tbl (event)values('A'),('b'),('c'),('d'),('e'),('A'),('b'),('c'),
('d'),('A'),('f')
CREATE TABLE #EventDetails(event nvarchar(5),groupId int)
DECLARE @event_name varchar(20),@group_id int=0
DECLARE event_cursor CURSOR FOR
SELECT event
FROM #tbl
OPEN event_cursor
FETCH NEXT FROM event_cursor
INTO @event_name
WHILE @@FETCH_STATUS = 0
BEGIN
if(@event_name ='a')
begin
set @group_id = @group_id+1
insert into #EventDetails (event ,groupId)
values (@event_name,@group_id)
end
else
begin
insert into #EventDetails (event ,groupId)
values (@event_name,@group_id)
end
FETCH NEXT FROM event_cursor
INTO @event_name
END
CLOSE event_cursor;
DEALLOCATE event_cursor;
select * from #EventDetails
drop table #EventDetails
drop table #tbl
=====================
Result
=====================
event groupId
A 1
b 1
c 1
d 1
e 1
A 2
b 2
c 2
d 2
A 3
f 3