JOIN alternatives to Sub Query
I'm trying to show a logged in user the number of notifications that they haven't seen yet each time they logged in. To that end I have the following query:
"select count(eventId) as count from notifications where updateId in("
# 2-the updates NOT IN what the user has seen
"select updateId from updates where updateId not in("
# 1-the updates the user has seen
"select updateId from seen_updates where memberId={}))".format(memberId))
The problem is this seems to take a while as the number of notifications increases. Is there a way to do this better with a join?
mysql> describe notifications; +----------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+---------+-------+ | eventId | int(10) unsigned | NO | | NULL | | | updateId | int(10) unsigned | YES | | NULL | | +----------+------------------+------+-----+---------+-------+ 2 rows in set (0.00 sec) mysql> describe updates; +---------------+------------------+------+-----+-------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+------------------+------+-----+-------------------+----------------+ | updated | timestamp | NO | | CURRENT_TIMESTAMP | | | updateId | int(10) unsigned | NO | PRI | NULL | auto_increment | | eventCategory | varchar(40) | YES | | NULL | | | eventsCount | int(10) unsigned | NO | | NULL | | +---------------+------------------+------+-----+-------------------+----------------+ 4 rows in set (0.00 sec) mysql> describe seen_updates; +----------+------------------+------+-----+-------------------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+------------------+------+-----+-------------------+-------+ | updateId | int(10) unsigned | NO | | NULL | | | memberId | int(10) unsigned | NO | | NULL | | | updated | timestamp | NO | | CURRENT_TIMESTAMP | | +----------+------------
With joins you could do it like this:
select count(eventId) as count
from notifications
inner join updates
on updates.updateId = notifications.updateId
left join seen_updates
on seen_updates.updateId = notifications.updateId
and seen_updates.memberId = {}
where seen_updates.updateId is null
Depending on your data structure, you might even not need the clause with inner join updates
. It seems logical that an notification.updateId
needs to have an existing counterpart in the updates
table. Only if this is not guaranteed that inner join
needs to stay.
上一篇: 何时使用日期时间或时间戳
下一篇: 加入子查询的替代方案