【问题标题】:MySQL: Find users with no submissionMySQL:查找没有提交的用户
【发布时间】:2015-09-21 02:12:49
【问题描述】:

我正在为一个查询而苦苦挣扎,希望您能提供帮助。 我有两张桌子。与所有用户一起使用,并与已提交表单中的信息一起使用。 两者都包含用户 ID。 我需要找出用户表中的哪个用户没有出现在报告表中。

这是我目前所拥有的:

SELECT u.ID, u.display_name, u.user_email, r.user_id
FROM users AS u
LEFT JOIN report AS r ON u.ID = r.user_id
WHERE NOT EXISTS(
    SELECT * 
    FROM report AS rr
    WHERE u.ID = rr.user_id
)

对于绝对从未提交过表单的用户来说,这似乎很好。 但是报告表还包含一个日期列,我想知道如何按天分组。 在前端,我希望有一个表格显示:

date: user:
2015-01-01 user a
2015-01-01 user f
2015-01-02 user g
2015-01-02 user a
2015-01-03 user z
2015-01-03 user x

其中的用户是当天没有提交表单的用户。

希望您能提供帮助。预先感谢!

【问题讨论】:

  • 你的意思是你想要报告表中不存在的日期明智的用户列表?
  • 如何从没有报告的用户的报告表中获取日期?你的问题没有意义。
  • @GordonLinoff,这就是为什么我想知道是否必须以某种方式更改表格以使其成为可能。但作为 Emipro Technologies Pvt。 Ltd. 说,我想知道是否有一种方法可以查询报告表中存在的所有日期,然后在用户表中找到没有日期/用户 ID 组合的用户。

标签: mysql sql where-clause not-exists


【解决方案1】:

如果您想获取报告表中没有任何行的用户列表,那么您可以生成一个集合,该集合是用户和报告表中存在的日期的笛卡尔积,然后对该集合进行左连接并检查是否为空。

交叉连接形成的笛卡尔集合将包含所有可能的日期和用户组合;也就是说,报告表将包含所有用户在所有可用日期添加的报告。

select r.date, u.user_id 
from report r 
cross join users u
left join (select r.date, r.user_id from users as u join report as r on u.id = r.user_id)
a on a.date = r.date and a.user_id = u.user_id
where a.date is null

Sample SQL Fiddle

对于大多数其他数据库,这可以通过设置差异运算符(减号或除号)而不是左连接来完成。

【讨论】:

    【解决方案2】:

    我正在为您的报告表中的列名做出假设:

    SELECT x.report_date, u.user_id, u.display_name
    FROM users u
    JOIN (
      SELECT DISTINCT report_date
      FROM reports
    ) x
    LEFT JOIN reports r
      ON r.user_id = u.user_id
      AND r.report_date = x.report_date
    WHERE r.report_date IS NULL
    ORDER BY x.report_date, u.user_id
    

    看看这个小提琴:http://sqlfiddle.com/#!9/407ac/5

    【讨论】:

    • 这很好用。我是否可以从报告表中添加其他列,或者由于日期选择不同而无法添加?
    • 您无法从报告表中选择其他列,因为您正在查找该表中没有记录的实例。 SELECT DISTINCT 仅用于获取可能日期的列表。这种方法的一个缺陷是,如果某个日期没有人提供报告,则该日期将不会显示在结果中。
    • 感谢您的解释。我设法通过添加一个子查询并使用给定的 ID 从第三个表中获取位置来完成它。没有人提交时没有显示日期这一事实对我来说并不是一个缺陷。那只是意味着它的星期日或银行假日,我真的不需要看到这些日期。
    【解决方案3】:

    使用 where 子句的左外连接...

    这是一个很好的链接...

    http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/

    SELECT * FROM `users`
    LEFT OUTER JOIN `report`
    ON `users`.`ID` = `report`.`user_id`
    WHERE `report`.`user_id` IS null
    ORDER BY `report`.`Date`
    

    【讨论】:

    • 不能解决操作的问题。他希望它按日期过滤。您可以编辑您的答案以包含它。
    • @AlanFrancis 喜欢吗?只是一个 Order by right,因为 group by 在他提供的示例中不起作用。
    • 谢谢大家。但这基本上给了我与原始查询相同的结果,只是顺序不同。同样在这里,我从用户列中选择所有信息,但我不知道哪一天谁忘记了填写表格。问题是用户必须每天填写此表格,我需要能够查看所有日期以及尚未填写的用户。有任何想法吗?我是否需要更改表格并添加一些字段才能完成这项工作?
    • 不管你信不信,仍在努力。我有两个人需要同样的东西。哈哈。一切都很容易,只是把日期弄对了。呜呜……
    • @NotoriousPet0 非常感谢!
    【解决方案4】:

    您当然可以只传递您想要检查的日期吗?

    像这样(使用@reportDate作为参数):

    SELECT * FROM users
    LEFT OUTER JOIN report
    ON users.ID = report.user_id
    WHERE report.user_id IS NULL
    AND report.Date = @reportDate
    

    【讨论】:

      【解决方案5】:

      您可以在没有报告的情况下获得成对的用户/日期。使用cross join 生成所有可能的行,然后过滤掉存在的行:

      select u.*, r.date
      from users u cross join
           (select distinct date from reports r) d left join
           reports r
           on u.id = r.user_id and d.date = r.date
      where r.userid is null;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多