【问题标题】:Select all from table where another query retuns no results从另一个查询不返回结果的表中全选
【发布时间】:2015-06-20 14:39:03
【问题描述】:

我正在为某人创建一个注册网络应用程序,并且我希望通过学生搜索将学生添加到活动注册中稍微准确一些。

目前我准备好的声明是:

("SELECT * FROM students WHERE first_name LIKE :pattern OR last_name LIKE :pattern OR id LIKE :pattern ORDER BY last_name ASC");

而且效果很好。我返回与搜索查询匹配的所有学生的列表。但是,在执行该查询之后,对于返回的每一行,我想检查 student.id 和 $_GET['activity'] 是否已经出现在参与者表中。

$_GET['activity'] 是来自activity.id 的ID

我想要的最终结果是显示所有尚未注册该活动的学生。

这可以在一个查询中实现吗?好像我宁愿那样做,然后必须对每个返回结果运行查询以查看是否应该显示它。

我已经研究过 INNER JOIN,因为我以前使用过它,但我觉得这不是我需要的。我的主要问题是如何运行该查询来检查每个结果是否已经在参与者表中。

希望这是有道理的,因为我发现很难在脑海中弄清楚如何表达它。

我的表结构:

学生 - id PRIMARY KEY AI、first_name (varchar255)、last_name (varchar255)、dob(日期)

活动 - id PRIMARY KEY AI、标题 (varchar255)、描述 (varchar255)

参与者 - id PRIMARY KEY AI、student_id (INT)、activity_id (INT)

【问题讨论】:

  • 这可以在一个查询中完成,但是您想从该查询中返回什么?您想要未注册该活动的学生,还是已注册的学生?
  • 我会将其添加到我的问题中。很抱歉不清楚。我想退回尚未在该活动中注册的学生。
  • 您显示的查询选择了一组学生。不过,您并没有给我们任何关于您的数据库如何记录学生活动的提示。
  • 您能否提供一下您的参与者表结构?
  • 更新了原始帖子以包含表格结构。谢谢。

标签: php mysql


【解决方案1】:

编辑更新它以使用问题中的三个表

如果您想要所有没有特定活动的学生,您可以使用这样的查询模式。 LEFT JOIN 保留 students 表中的所有记录,并将 NULL 值放置在 activities 的列中,其中 ON 条件不匹配。 然后你抛出一个WHERE 条件仅保留那些 NULL 值。像这样:

 SELECT s.id, s.first_name, s.last_name
   FROM students s
   LEFT JOIN participants p ON s.id = p.student_id
   LEFT JOIN activities a ON p.activity_id = a.activity_id AND a.activity LIKE :act
  WHERE a.activity_id IS NULL
    AND ( s.first_name LIKE :a OR s.last_name LIKE :b OR etc etc )

如果您输入的是activity_id,那就更简单了。

 SELECT s.id, s.first_name, s.last_name
   FROM students s
   LEFT JOIN participants p ON s.id = p.student_id AND p.activity_id = :act
  WHERE p.activity_id IS NULL
    AND ( s.first_name LIKE :a OR s.last_name LIKE :b OR etc etc )

正如您所注意到的,INNER JOIN 不能这样做,因为它会从第一个表中忽略不符合 ON 条件的行。但是这些行正是您想要的,因此是LEFT JOIN ... WHERE ... IS NULL

注意一些事情:

  • 不要使用 LIKE 来匹配 id 值。
  • 不要使用SELECT *。相反,请在结果集中命名您想要的列。
  • 学生表过滤器中的OR ... LIKE 子句序列不会很好地执行。

【讨论】:

  • 非常感谢。第二个查询完美运行。我将离开并阅读有关 LEFT JOIN 的内容,以便在继续之前能够正确理解它。再次感谢。
【解决方案2】:

您可以使用子查询来获取为$_GET['activity'] 注册的studentids,然后在WHERE 条件中使用NOT IN 从返回的行中删除它们。

SELECT * FROM students 
WHERE 
   (first_name LIKE :pattern OR last_name LIKE :pattern OR id LIKE :pattern)
AND 
   id NOT IN 
        (SELECT student_id FROM participants WHERE activity_id = :activity)
ORDER BY last_name ASC

其中:activity$_GET['activity'] 的占位符

【讨论】:

    【解决方案3】:

    试试这个查询

    "SELECT * FROM students WHERE first_name LIKE :pattern OR last_name LIKE :pattern OR id LIKE :pattern AND id NOT IN (select student_id From participants WHERE activity_id = activity)
    

    这里的“活动”是$_GET['活动']

    【讨论】:

    • 您好米兰,感谢您的建议。如果我是正确的,NOT IN(从参与者中选择 student_id)将不起作用,因为如果参与者是其他活动的一部分,则参与者中可能有多个相同 student_id 的条目。例如,如果您在 activity.id 2 上进行搜索,但学生已经是 activity.id 1 的一部分。
    • 另外,您的查询中有 2 个WHEREs,这是无效的 sql 语法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多