我真的不知道如何命名一个话题,请原谅我:c 我想从数据库中获取一些统计信息。我有3张桌子,就像这样:
Sent messages:
id(send_id)
stamp(timestmap)
Replies:
id
send_id
stamp(timestamp)
Opened:
id
send_id
stamp
问题是在打开的表中我保存每个用户邮件打开的标记。因此,如果用户打开我的电子邮件3次,则有3封邮件:
id [1, 2, 3]
send_id [1, 1, 1]
stamp [2017-08-06 15:15:12, 2017-08-07 12:11:12, 2017-08-08 20:15:05]
现在,我希望每天都有统计数据,如下所示:
sent opened replied date
50 35 10 2017-08-01
20 15 5 2017-08-02
125 80 20 2017-08-03
这是我的问题,这是否可以检查前一行中是否已存在特定的send_id,并跳过计数,因为现在,如果用户在3天不同的时间打开电子邮件,那么我每天都有+1,但是它应该只在他打开它的第一天加1。
我当前的选择:
select COUNT(DISTINCT s.id) as "sent",
COUNT(DISTINCT CASE WHEN o.send_id is NULL THEN NULL ELSE s.id END) as "opened",
COUNT(DISTINCT CASE WHEN r.send_id is NULL THEN NULL ELSE s.id END) as "replied",
o.stamp::timestamp::date as date
from db_send s
left join db_reply r ON(r.send_id = s.id)
left join db_send_open o ON (o.send_id = s.id)
group by date
order by date
所以问题是:我有更多的已打开邮件,因为我不知道如何仅通过send_id对它们进行分组(不是按日期,但我也必须按日期分组:ccc,所以利益冲突并选择一个日期最短的
答案 0 :(得分:1)
你可以在CTE中预先打开数据,如:
with db_send_open as (
select min(stamp) stamp, send_id
from db_send_open
group by send_id
)
select COUNT(DISTINCT s.id) as "sent",
count (o.send_id) as "opened",
COUNT(DISTINCT CASE WHEN r.send_id is NULL THEN NULL ELSE s.id END) as "replied",
o.stamp::timestamp::date as date
from db_send s
left join db_reply r ON(r.send_id = s.id)
left join db_send_open o ON (o.send_id = s.id)
group by date
order by date
答案 1 :(得分:1)
以下是可以解决您的问题的查询。它与Vao提供的几乎相同。但是CTE通常在运行时占用数据库中的内存空间,因为CTE可以在查询脚本中多次使用。仅当重用相同的结果集时,建议才使用CTE。由于这是一个邮件系统,我认为你处理的记录非常高,因此CTE可能会降低你的表现。
如果永远不打开邮件,我也假设将sendtime作为opendate。如果不需要,您可以删除案例陈述。
select case when b.opendate is null then date(a.senttime) else b.opendate
end opendate,count(a.id) mail_sent,count(b.send_id) "read",count(distinct
c.send_id) replied
from waggle.sent_kn a
left join
(select send_id,date(min(opentime)) opendate from
waggle.opened_kn
group by send_id)b
on a.id=b.send_id
left join waggle.replied_kn c
on c.send_id = a.id
group by case when b.opendate is null then date(a.senttime) else b.opendate
end;
希望这有帮助!! :)