![](/img/trans.png)
[英]Sql query to join 2 tables and count the values matching and non matching rows
[英]Sql self join along with non matching rows
我有一张这样的桌子
id | user | name | action | created_at
--------------------------------------------------
1 | 42 | eve | open | 2020-01-06 06:17:42
2 | 42 | eve | close | 2020-01-06 06:27:42
3 | 42 | eve | open | 2020-01-06 06:37:42
4 | 42 | eve | close | 2020-01-06 06:47:42
5 | 42 | eve | open | 2020-01-06 06:57:42
我需要得到这张表:
user | name | open | open_created_at | close | close _created_at
-----------------------------------------------------------------------
42 | eve | open | 2020-01-06 06:17:42 | close | 2020-01-06 06:27:42
42 | eve | open | 2020-01-06 06:37:42 | close | 2020-01-06 06:47:42
42 | eve | open | 2020-01-06 06:57:42 | null | null
这是我得到的表:
SELECT t1.user, t1.name, t1.action, t1.created_at, t2.action, t2.created_at
FROM tabel t1, table t2
WHERE t1.user = t2.user AND t1.action = 'open' AND t2.action = 'close' AND t1.created_at < t2.created_at
GROUP BY t1.id
user | name | open | open_created_at | close | close _created_at
-----------------------------------------------------------------------
42 | eve | open | 2020-01-06 06:17:42 | close | 2020-01-06 06:27:42
42 | eve | open | 2020-01-06 06:37:42 | close | 2020-01-06 06:47:42
如何在同一列中获得具有匹配打开/关闭的表以及没有匹配关闭列的行?
您需要使用LEFT JOIN
而不是INNER JOIN
,并且需要将WHERE
子句移动到JOIN
条件中。 您还应该在t2
值周围添加聚合函数以确保一致的结果:
SELECT t1.user, t1.name, t1.action AS open, t1.created_at AS open_created_at,
MIN(t2.action) AS close, MIN(t2.created_at) AS close_created_at
FROM log t1
LEFT JOIN log t2 ON t1.user = t2.user AND t2.action = 'close' AND t1.created_at < t2.created_at
WHERE t1.action = 'open'
GROUP BY t1.id, t1.name, t1.action, t1.created_at
输出:
user name open open_created_at close close_created_at
42 eve open 2020-01-06 06:17:42 close 2020-01-06 06:27:42
42 eve open 2020-01-06 06:37:42 close 2020-01-06 06:47:42
42 eve open 2020-01-06 06:57:42 (null) (null)
另一种方法是将过程分为 3 个步骤:
收集所有open
行并按created_at
按升序对它们进行排序。 在此过程中,创建一个变量,例如@rank
以按升序为每一行分配排名,如 1,2,3 等等。
收集所有close
行并按created_at
按升序对它们进行排序。 在此过程中,创建一个变量,例如@rank2
,以升序为每一行分配排名,如 1,2,3 等等。
现在,根据rank
对两个表进行left join
。
查询片段:
select d1.user,d1.name,d1.action as open,d1.open_created_at,d2.action as close,d2.close_created_at
from
(
select @rank := @rank + 1 as rank,user,name,action,created_at as open_created_at
from log,(select @rank := 0) l1
where action = 'open'
order by created_at asc
) d1
left join
(
select @rank2 := @rank2 + 1 as rank,user,name,action,created_at as close_created_at
from log,(select @rank2 := 0) l2
where action = 'close'
order by created_at asc
) d2
on d1.rank = d2.rank
数据库小提琴: https : //www.db-fiddle.com/f/hYHyz45rtuiEXGQPbz3m6z/0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.