【问题标题】:join and group table a rows by table b dates按表 b 日期连接和分组表 a 行
【发布时间】:2019-01-19 03:24:51
【问题描述】:

我有两个 m:m 表,profile_wordcardsprofile_activities。我想按活动创建日期对所有单词卡进行分组,其中profile_id = 2

即,如果在2019-01-19 2:12:05 上创建了activity 1,则在该日期或之前创建的任何单词卡都应按activity 1 分组。如果activity 2 是在2019-01-19 2:14:22 创建的,则在该日期或之前创建的所有单词卡都应按activity 2 分组,依此类推。

表格:profile_activities

activity_id | profile_id | created_at
------------------------------------------
1              2            2019-01-19 2:12:05
2              2            2019-01-19 2:14:22

表格:profile_wordcards

wordcard_id | profile_id | created_at   
-----------------------------------------   
386         2             2019-01-19 2:04:07    >> Everything below: less than activity 1 created at    
385         2             2019-01-19 2:05:19        
263         2             2019-01-19 2:05:19        
234         2             2019-01-19 2:11:49        
175         2             2019-01-19 2:12:02        
201         2             2019-01-19 2:12:02        
226         2             2019-01-19 2:12:04        
409         2             2019-01-19 2:12:05        
361         2             2019-01-19 2:12:05        
359         2             2019-01-19 2:12:25    >> Everything below: less than activity 2 created at    
188         2             2019-01-19 2:12:34        
227         2             2019-01-19 2:12:59        
187         2             2019-01-19 2:13:01        
228         2             2019-01-19 2:13:18        
384         2             2019-01-19 2:13:37        
177         2             2019-01-19 2:14:00        
225         2             2019-01-19 2:14:00        

期望的输出:

wordcard_id | profile_id |  created_at     | activity_id | activity_created_at
--------------------------------------------------------------------------------------- 
-- GROUP 1 (ACTIVITY ID 1, any wordcard.created_at <= 2019-01-19 2:12:05)
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
386             2       2019-01-19 2:04:07     1           2019-01-19 2:12:05
385             2       2019-01-19 2:05:19     1           2019-01-19 2:12:05
263             2       2019-01-19 2:05:19     1           2019-01-19 2:12:05
234             2       2019-01-19 2:11:49     1           2019-01-19 2:12:05
175             2       2019-01-19 2:12:02     1           2019-01-19 2:12:05
201             2       2019-01-19 2:12:02     1           2019-01-19 2:12:05
226             2       2019-01-19 2:12:04     1           2019-01-19 2:12:05
409             2       2019-01-19 2:12:05     1           2019-01-19 2:12:05
361             2       2019-01-19 2:12:05     1           2019-01-19 2:12:05
-- GROUP 2 (ACTIVITY ID 2, any wordcard.created_at <= 2019-01-19 2:14:22 but > 2019-01-19 2:12:05) 
-- >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
359             2       2019-01-19 2:12:25     2           2019-01-19 2:14:22
188             2       2019-01-19 2:12:34     2           2019-01-19 2:14:22
227             2       2019-01-19 2:12:59     2           2019-01-19 2:14:22
187             2       2019-01-19 2:13:01     2           2019-01-19 2:14:22
228             2       2019-01-19 2:13:18     2           2019-01-19 2:14:22
384             2       2019-01-19 2:13:37     2           2019-01-19 2:14:22
177             2       2019-01-19 2:14:00     2           2019-01-19 2:14:22
225             2       2019-01-19 2:14:00     2           2019-01-19 2:14:22

我试过了:

select pwc.wordcard_id, pwc.created_at, pa.activity_id, pa.created_at, pwc.profile_id
from profile_wordcards pwc
left join profile_activities pa on (pa.created_at < pwc.created_at)
where pwc.profile_id = 2
order by activity_id asc

但这会返回 a) 未附加到配置文件 2 的活动 ID 和 b) 未按预期分组。

【问题讨论】:

    标签: sql postgresql date group-by


    【解决方案1】:

    不要加入profile_activities,而是直接加入从profile_activitieslag()ed created_at 中选择所有列的子查询。然后您可以与“上一个”活动的created_at 进行比较。对于lag() 的默认值,当没有以前的活动存在时,使用'-infinity'。由于所有时间戳都大于负无穷大,因此与 wordcard created_at 的比较也适用于这种情况。

    SELECT w.wordcard_id,
           w.profile_id,
           w.created_at,
           a.activity_id,
           a.profile_id,
           a.created_at
           FROM (SELECT a.activity_id,
                        a.profile_id,
                        a.created_at,
                        lag(a.created_at,
                            1,
                            '-infinity') OVER (ORDER BY a.created_at) created_at_lag
                        FROM profile_activities a) a
                INNER JOIN profile_wordcards w
                           ON w.profile_id = a.profile_id
                              AND w.created_at > a.created_at_lag
                              AND w.created_at <= a.created_at
           ORDER BY a.activity_id;
    

    db<>fiddle

    【讨论】:

    • 惊人的工作! LAG 很棒,使用infinity 捕获低于第一个活动created_at 阈值的项目很棒
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    • 2019-07-29
    相关资源
    最近更新 更多