繁体   English   中英

MySQL - 两个表和两个连接

[英]MySQL - two tables and two joins

我被一个查询困住了,我想做几件事:-我有一个包含一些事件的表,每个事件都有有限数量的人可以申请它-在另一个表中,我记录了谁申请了哪个事件-在网站上,对用户,我只想显示他可以申请的事件(更准确地说,是他没有申请的事件;一旦他申请,该事件应该不再对用户可见) AND/OR 申请人数少于 max_no_people (当事件已满时,无需向用户显示

我在另一个线程中从这里获得了帮助,但仅针对部分问题。 表如下所示:

other_events (eventID, max_no_people, active)
event_applied (eventID, userID)

这是查询:

SELECT count(event_applied.eventid) AS no_applied, 
       e.eventID, e.max_no_people, e.active 
FROM other_events e 
     INNER JOIN 
     event_applied ON event_applied.eventID = e.eventID 
     LEFT JOIN 
     event_applied ea ON ea.eventID 
                      AND event_applied.userID = :userID 
WHERE ea.eventID IS NULL 
      AND e.active = 1
GROUP BY event_applied.eventID 
HAVING (no_applied < max_no_people)

此查询工作正常 - 但是 - 对于除当前所选用户之外的所有其他用户。 假设您的userID = 42 (不在与 eventID = 123 配对的 events_applied 表中):

其他事件

eventID | max_no_people | active
--------|---------------|-------
   21   |       5       |   1

并在 events_applied

eventID | userID
--------|-------
123     |  10
123     |  11
123     |  12
123     |  13
123     |  14

查询将返回空行(因为事件已被最大化,您无法再申请),但如果您是userID = 12 (在 events_applied 表中并具有 eventID 对),结果将如下所示:

no_applied | e.eventID | e.max_no_people | e.active
-----------|-----------|-----------------|---------
 **4**     |     123   |         5       |    1

因此,该事件将是可见的,您将能够一次又一次地应用(我知道我必须添加一些额外的控件,但我稍后会解决这个问题)。

所以,问题是这个查询以某种方式丢弃了当前用户的行并且没有将其添加到最终计数中。

有人吗? :)

问题是,在您当前的查询中,您只是明确排除了用户应用的条目,因此计数减一。 相反,您需要排除它们应用的所有事件。

由于您使用的是 LEFT JOIN,因此您需要对所有这些事件使用 select 的子查询,然后仅加入事件(而不加入用户)。

SELECT count(event_applied.eventid) AS no_applied, e.eventID, e.max_no_people, e.active 
FROM other_events e 
INNER JOIN event_applied ON event_applied.eventID = e.eventID 
LEFT JOIN (SELECT * FROM event_applied WHERE event_applied.userID = :userID ) ea 
ON ea.eventID = e.eventID 
WHERE ea.eventID IS NULL AND e.active = 1
GROUP BY e.eventID, e.max_no_people, e.active
HAVING (no_applied < max_no_people)

您的查询的主要问题是您没有left join ed 查询与特定eventID相关联。

考虑以下代码:

SELECT 
    COUNT(*) AS no_applied, 
    e.eventID, 
    e.max_no_people, 
    e.active 
FROM 
    other_events e 
    INNER JOIN event_applied ea1 ON ea1.eventID = e.eventID 
    LEFT JOIN event_applied ea2 ON ea1.eventID = ea2.eventID AND ea2.userID = :userID
WHERE ea2.eventID IS NULL AND e.active = 1
GROUP BY e.eventID, e.max_no_people, e.active 
HAVING (no_applied < e.max_no_people)

如果您使用示例数据在此 DB Fiddle 中运行此查询:

  • 使用userID = 42 ,它不返回任何记录:这是因为没有可用的事件(只有一个事件,已经满了)

  • 使用userID = 12时,它不返回任何记录:这是因为该用户已应用于唯一可用的事件

我建议创建一个更具代表性的数据集,例如通过创建另一个未满的事件,这样您就可以彻底验证查询。

谢谢Graeme TateGMB ,这两种方法都非常有效:我今天学到了一些新东西 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM