我有一个简单的SQL表,看起来像这样-
CREATE TABLE msg (
from_person character varying(10),
from_location character varying(10),
to_person character varying(10),
to_location character varying(10),
msglength integer,
ts timestamp without time zone
);
我想为表中的每一行找出过去3分钟内是否有不同的“ from_person”和“ from_location”与当前行中的“ to_person”进行了交互。
例如,在上表中,对于第4行,除了孟买的mary(当前行)之外,纽约市的nancy和巴塞罗那的bob也在最近3分钟内向charlie发送了一条消息,因此计数为2。
同样,对于第2行,除了巴塞罗那(当前行)的bob以外,只有纽约市的nancy向ca(当前行)的查理发送了一条消息,因此计数为1
示例所需的输出-
0
1
0
2
我尝试使用窗口函数,但似乎在frame子句中我可以指定前后的行数,但不能指定时间本身。
众所周知,Postgres中的每个表都有一个主键。或至少应该有。如果您有一个主键定义行的预期顺序,那就太好了。
示例数据:
create table msg (
id int primary key,
from_person text,
to_person text,
ts timestamp without time zone
);
insert into msg values
(1, 'nancy', 'charlie', '2016-02-01 01:00:00'),
(2, 'bob', 'charlie', '2016-02-01 01:00:00'),
(3, 'charlie', 'nancy', '2016-02-01 01:00:01'),
(4, 'mary', 'charlie', '2016-02-01 01:02:00');
查询:
select m1.id, count(m2)
from msg m1
left join msg m2
on m2.id < m1.id
and m2.to_person = m1.to_person
and m2.ts >= m1.ts- '3m'::interval
group by 1
order by 1;
id | count
----+-------
1 | 0
2 | 1
3 | 0
4 | 2
(4 rows)
如果没有主键,则可以使用函数row_number()
,例如:
with msg_with_rn as (
select *, row_number() over (order by ts, from_person desc) rn
from msg
)
select m1.id, count(m2)
from msg_with_rn m1
left join msg_with_rn m2
on m2.rn < m1.rn
and m2.to_person = m1.to_person
and m2.ts >= m1.ts- '3m'::interval
group by 1
order by 1;
请注意,我习惯于row_number() over (order by ts, from_person desc)
获取问题中所介绍的行的顺序。当然,您应该自己决定如何解决由相同列值ts
(如前两行)引起的歧义。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句