mysql select 来自 Table A(在条件下)而不在 Table B(在相同条件下)

mysql select from Table A (on conditions) where not in Table B (on same conditions)

我在这件事上玩得很开心。我一直在阅读和尝试不同的解决方案,但 none 对我有用。我已经创建了一个抽奖系统,需要 select 满足所有条件的用户,这些用户以前没有根据相同条件 selected。

TableA 字段,用户已签到位置:

chID | ceID | cID  | crID | clID | user_ID | chTime   | chDate
1      1135   1001   1001   1163   8213451   17:21:30   2022-04-21
2      1135   1001   1001   1163   8213452   17:22:30   2022-04-21
3      1135   1001   1001   1163   8213453   17:23:30   2022-04-21
4      1135   1001   1001   1163   8213454   17:24:30   2022-04-21
5      1135   1001   1001   1163   8213455   17:25:30   2022-04-21

6      1155   1021   1001   1183   9213451   17:21:30   2022-04-21
7      1155   1021   1001   1183   9213452   17:22:30   2022-04-21
8      1155   1021   1001   1183   9213453   17:23:30   2022-04-21
9      1155   1021   1001   1183   9213454   17:24:30   2022-04-21
10     1155   1021   1001   1183   9213455   17:25:30   2022-04-21

11     1136   1002   1001   2163   8213451   17:21:30   2022-04-21
12     1136   1002   1001   2163   8213452   17:22:30   2022-04-21
13     1136   1002   1001   2163   8213453   17:23:30   2022-04-21
14     1136   1002   1001   2163   8213454   17:24:30   2022-04-21
15     1136   1002   1001   2163   8213455   17:25:30   2022-04-21

注意:1-5 和 11-15 是同一个用户,但是组类别 ID 不同

TableB 个字段,用户之前 select 被选为获胜者:

bID | ceID | cID  | crID | clID | user_ID | chTime   | chDate
1     1135   1001   1001   1163   8213451   17:21:30   2022-04-21
2     1155   1021   1001   1183   9213454   17:24:30   2022-04-21
3     1136   1002   1001   2163   8213453   17:23:30   2022-04-21

Table A 存储已签入特定组的用户。 Table 当来自该组的用户 select 参加抽奖时,B 会存储该用户。

我需要能够 select 来自 Table A 基于群组签到信息,而 TableB 基于相同的群组签到信息。

对于这个例子,我需要 select 一个用户,其中: ceID=1135、cID=1001、crID=1001、clID=1163 和 chDate=2022-04-21 根据相同的标准,Table B 中不存在:

// This returns user from wrong group:
select ch.user_ID FROM TableA ch 
  WHERE NOT EXISTS (
    select 1 FROM tableB cr 
      WHERE ch.cID=1001 AND ch.cID=cr.cID
        AND ch.crID=1001 AND ch.crID=cr.crID
        AND ch.clID=1163 AND ch.clID=cr.clID
        AND ch.ceID=1135 AND ch.ceID=cr.ceID
        AND ch.user_ID=cr.user_ID
        AND ch.chDate='2022-04-21' AND ch.chDate=cr.chDate
  ) 
  Group by ch.user_ID 
  ORDER BY RAND() LIMIT 1

// This returns nothing:
SELECT ch.* FROM tableA ch 
  left join tableB cr on ch.user_ID=cr.user_ID 
  WHERE ch.cID=1001 AND cr.cID=1001
    AND ch.crID=1001 AND cr.crID=1001  
    AND ch.clID=1163 AND cr.clID=1163  
    AND ch.ceID=1135 AND cr.ceID=1135  
    AND ch.chDate='2022-04-21' AND cr.chDate='2022-04-21'
    AND cr.user_ID IS NULL  
    GROUP BY ch.user_ID 
    ORDER BY RAND() LIMIT 1
  ;

我已经对两者进行了几次不同的迭代,但都无济于事。

我会这样写:

SELECT ch.* FROM tableA AS ch 
LEFT OUTER JOIN tableB AS cr 
  ON ch.user_ID=cr.user_ID 
  AND cr.cID=1001 
  AND cr.crID=1001 
  AND cr.clID=1163 
  AND cr.ceID=1135 
  AND cr.chDate='2022-04-21'
WHERE ch.cID=1001
  AND ch.crID=1001
  AND ch.clID=1163
  AND ch.ceID=1135
  AND ch.chDate='2022-04-21'
  AND cr.user_ID IS NULL  
GROUP BY ch.user_ID 
ORDER BY RAND() LIMIT 1;

如果要在该外部联接中的 cr table 上放置条件,请将条件放置在 ON 子句中。如果将条件放在 WHERE 子句中,则意味着列必须是 non-NULL,这意味着连接中必须有匹配项。但是您正在寻找 no 符合这些条件的行满足连接的情况。

顺便说一下,我不确定 GROUP BY。除非 user_idtableA 的主键或唯一键,否则其他列在功能上不相关,分组应该是错误的。但是,如果该列是主键或唯一键,那么分组就是 no-op,所以我不确定它为什么在那里。