SQL 将行分组为对
Posted
技术标签:
【中文标题】SQL 将行分组为对【英文标题】:SQL group rows into pairs 【发布时间】:2018-05-10 16:34:04 【问题描述】:我正在尝试将某种唯一标识符 (uid) 添加到由成对行组成的分区中,即在大小 = 2 行的窗口分区中为 (identifier1,identifier2) 的每两行生成一些 uid/tag .
因此,例如,ID X 的前 2 行将获得 uid A,相同 ID 的接下来两行将获得 uid B,如果在 ID X 的分区中只剩下一行,它会得到 id C。
这是我想要完成的,图片说明了表的结构,我手动添加了预期标识符来说明目标:
这是我目前的SQL,ntile没有解决,因为分区大小不同:
select
rowId
, ntile(2) over (partition by firstIdentifier, secondIdentifier order by timestamp asc) as ntile
, *
from log;
已经尝试过 ntile((count(*) over partition...) / 2),但这不起作用。
可以使用 md5() 或类似方法生成 UID,但我无法如上所示标记行(因此我可以 md5 生成的标记/uid)
【问题讨论】:
【参考方案1】:虽然 Snowflake 窗口函数不支持 count(*),但支持 count(1) 并可用于创建唯一标识符。下面是一个整数唯一 ID 匹配行对并处理“奇数”行组的示例:
select
ntile(2) over (partition by firstIdentifier, secondIdentifier order by timestamp asc) as ntile
,ceil(count(1) over( partition by firstIdentifier, secondIdentifier order by timestamp asc) / 2) as id
, *
from log;
【讨论】:
几乎解决了,但是高亮的行应该设置为1而不是2:imgur.com/a/MGv7yrC 我无法重现该问题:即使时间戳与您的屏幕截图中的相同,我仍会继续获得该数据的 1、2、3 对。你能发布你用来生成结果的完整 SQL 吗?【参考方案2】:select *, char(65 + (row_number() over(partition by
firstidentifier,secondidentifier order by timestamp)-1)/2)
expectedidentifier from log
order by firstidentifier, timestamp
这是 Sql Server 版本
with log (firstidentifier,secondidentifier, timestamp)
as (
select 15396, 14460, 1 union all
select 15396, 14460, 1 union all
select 19744, 14451, 1 union all
select 19744, 14451, 1 union all
select 19744, 14451, 1 union all
select 15590, 12404, 1 union all
select 15590, 12404, 1 union all
select 15590, 12404, 1 union all
select 15590, 12404, 1 union all
select 15590, 12404, 1
)
select *, char(65 + (row_number() over(partition by
firstidentifier,secondidentifier order by timestamp)-1)/2)
expectedidentifier from log
order by firstidentifier,secondidentifier,timestamp
【讨论】:
谢谢,但这并没有输出预期的结果 对不起,我错过了时间戳相同的情况。用 row_number 更新了查询。现在应该可以工作了。以上是关于SQL 将行分组为对的主要内容,如果未能解决你的问题,请参考以下文章