MySQL-两个表和两个联接

时间:2019-10-23 11:20:54

标签: mysql sql

我陷入一个查询,我想做几件事: -我有一张桌子,上面有一些事件,每个事件的人数都有限 -在其他表格中,我记录了谁申请了哪个活动 -在网站上,我只想向用户显示他可以应用的事件(更确切地说,他尚未应用的事件;一旦他应用,则该事件将不再对用户可见)和/或应用的人数少于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表中):

other_events

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

因此,该事件将可见,您将能够一次又一次地申请(我知道我必须添加一些其他控件,但稍后再解决)。

因此,问题在于该查询以某种方式丢弃了当前用户的行,并且没有将其添加到最终计数中。

有人吗? :)

3 个答案:

答案 0 :(得分:0)

问题在于,在当前查询中,您仅明确排除了用户已应用的条目,因此该计数减少了一个。相反,您需要排除所有应用了事件的事件。

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

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)

答案 1 :(得分:0)

查询的主要问题是您没有关联与特定left join上的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)

如果您使用示例数据运行此查询 in this DB Fiddle

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

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

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

答案 2 :(得分:0)

感谢Graeme TateGMB,这两种方法都可以正常工作! 我今天学到了一些新东西:)