Multi SELECT 查询多个id

Multi SELECT query for multiple ids

我执行 SELECT 来决定是否向用户发送通知。 (10.3.23-MariaDB)

第一部分检查是否有 0 个未读通知,如果为 0,则不再需要 SELECT

如果不是,我会计算自上次相同通知以来用户有多少通知(在这种情况下总是有一个可以计算)并检查未读通知数量 user_sess.unread_noti

SELECT 'yes' AS do_insert 
  FROM 
     (SELECT unread_noti 
        FROM user_sess 
      WHERE user_id = 100)user_sess 
 WHERE user_sess.unread_noti = 0 
    OR (SELECT COUNT(*) FROM notification
            WHERE user_id=100 AND id > 400
       ) >= user_sess.unread_noti

现在我想检查多个用户的相同通知,并通过对多个用户执行 SELECT 来提高效率,例如像这个(不正确的例子):

SELECT  user_sess.user_id
    FROM  user_sess
    LEFT JOIN  notification  ON user_sess.unread_noti > 0
      AND  notification.id > 400
      AND  notification.user_id=user_sess.user_id
    WHERE  user_sess.user_id IN (100,101)
      AND  ( user_sess.unread_noti = 0
              OR  COUNT(notification.id) >= user_sess.unread_noti
           ) 

要计数的 notification.id 对于多个用户来说可以是相同的,因为我 INSERT 它们是批量的,因此它们将占据相同的“位置”。

notification:
id        Primary   int(11) 
user_id   Index     int(11) 

user_sess:
user_id     Primary int(11)
unread_noti         tinyint(3)

我建议你尝试在 2 SELECTs 内完成,而不考虑用户 ID 的数量。

那个人会得到所有的用户 ID WHERE unread_noti = 0

其他人会得到那些 unread_noti != 0 AND ...

我假设 table 正在被其他线程修改?所以,使用事务:

BEGIN;
SELECT ... WHERE unread_noti = 0          FOR UPDATE;
SELECT ... WHERE unread_noti != 0 AND ... FOR UPDATE;
...
INSERT ...
COMMIT;

为什么?

  • OR没有优化好
  • FOR UPDATE 可以解决任何并发问题
  • 单独考虑每个 SELECT 更容易。

您可以使用 group byhaving 如下:

SELECT u.user_id, 'yes' AS do_insert 
  FROM user_sess u 
  LEFT JOIN notification N ON u.user_id = n.user_id AND n.id > 400
 Where u.user_id in (100, 101)
Group by u.user_id, u.unread_noti
Having max(u.unread_noti) = 0 OR count(N.USER_ID) > u.unread_noti