【问题标题】:MySQL select only the newest records older than 2 days (timestamp)MySQL 仅选择超过 2 天的最新记录(时间戳)
【发布时间】:2013-08-28 12:54:09
【问题描述】:

我有一个人员表、一个单位表和一个健康表(如下所述)。基本上在我的工作中,我们必须检查人员,如果他们已经两天没有出现,我们就会去寻找他们......我想要的是能够从健康表中选择所有记录超过两天,但只有最新的(因为每人每天可能会有多个条目,这就是我想要的,因为使用 wellness.username 字段您可以知道谁在什么时候看到了谁)。

People 
+------------+-------------+------+-----+-------------------+----------------+
| Field      | Type        | Null | Key | Default           | Extra          |
+------------+-------------+------+-----+-------------------+----------------+
| id         | int(11)     | NO   | PRI | NULL              | auto_increment |
| fname      | varchar(32) | NO   |     | NULL              |                |
| lname      | varchar(32) | NO   |     | NULL              |                |
| dob        | date        | NO   |     | 0000-00-00        |                |
| license_no | varchar(24) | NO   |     | NULL              |                |
| date_added | timestamp   | NO   |     | CURRENT_TIMESTAMP |                |
| status     | varchar(8)  | NO   |     | Allow             |                |
+------------+-------------+------+-----+-------------------+----------------+

Units
+----------+-------------+------+-----+---------+----------------+ 
| Field    | Type        | Null | Key | Default | Extra          |
+----------+-------------+------+-----+---------+----------------+
| id       | int(11)     | NO   | PRI | NULL    | auto_increment |
| number   | varchar(3)  | NO   |     | NULL    |                |
| resident | int(11)     | NO   | MUL | NULL    |                |
| type     | varchar(16) | NO   |     | NULL    |                |
+----------+-------------+------+-----+---------+----------------+

+--------------+-------------+------+-----+-------------------+----------------+
| Field        | Type        | Null | Key | Default           | Extra          |
+--------------+-------------+------+-----+-------------------+----------------+
| wellness_id  | int(11)     | NO   | PRI | NULL              | auto_increment |
| people_id    | int(11)     | NO   |     | NULL              |                |
| time_checked | timestamp   | NO   |     | CURRENT_TIMESTAMP |                |
| check_type   | varchar(1)  | NO   |     | NULL              |                |
| username     | varchar(16) | NO   |     | jmd9qs            |                |
+--------------+-------------+------+-----+-------------------+----------------+

units 表很丑,我知道,但很快就会改变;就目前而言,resident 引用了people.id

这是我的最小工作示例,即使 wellness 中有多个 peopletime_checked 行早于 2 天,它也只会给我一个结果。我得到的一个结果更像是 4-1/2 天大......

select w.wellness_id, p.id, p.lname, p.fname, u.number, u.type,
w.time_checked, w.check_type, w.username 
from people p 
    left join units u on p.id = u.resident
    right join wellness w on p.id = w.people_id 
    WHERE w.time_checked <= DATE_ADD(CURDATE(), INTERVAL -2 DAY)
order by w.time_checked asc;

我正在尝试获取超过两天的最新记录,但 wellness 表中的每个 people 只有 1 条。我加入了所有其他的东西,因为我需要它来用 PHP 显示记录。

对不起,我的问题很漫无边际,希望它足够清楚!

编辑 - 示例数据:

+------+------+--------+---------------------+------------+----------+
| w_id | id   | number | time_checked        | check_type | username |
+------+------+--------+---------------------+------------+----------+
|  100 |    2 | 425    | 2013-08-23 21:03:00 | s          | jmd9qs   |
|  101 |    2 | 425    | 2013-08-25 05:41:01 | s          | jmd9qs   |
|   91 |    2 | 425    | 2013-08-20 19:52:23 | s          | jmd9qs   |
|   83 |    4 | 416    | 2013-08-23 20:12:29 | s          | jmd9qs   |
|   76 |    5 | 408    | 2013-08-23 20:11:21 | s          | jmd9qs   |
|   62 |    6 | 327    | 2013-08-23 20:06:13 | s          | jmd9qs   |
|   18 |    7 | 204    | 2013-08-23 19:43:58 | s          | jmd9qs   |
|   31 |    8 | 219    | 2013-08-23 19:51:11 | s          | jmd9qs   |
|   97 |    9 | 432    | 2013-08-23 20:16:39 | o          | jmd9qs   |
|   44 |   10 | 309    | 2013-08-23 19:55:45 | s          | jmd9qs   |
+------+------+--------+---------------------+------------+----------+

【问题讨论】:

  • 你能提供样本数据和基于它的期望输出吗?
  • 由于它的性质,我无法真正向您展示示例数据,但我真正需要返回的只是与我的匹配的 people.idpeople.fnamepeople.lnameunit.number标准 a) 2 天未见和 b) 每人只有一个结果
  • 可能是假数据,没有人对真数据感兴趣。但需要更好地了解您的要求,其次是测试查询。否则我们需要花时间自己弥补。
  • 这个问题可能会有所帮助:stackoverflow.com/questions/7194547/…
  • 为什么要为 id=2 设置一行?他有一个日期为 2013-08-25 的条目,你还不需要去找他。

标签: mysql join timestamp


【解决方案1】:

这是得到我想要的查询:

select p.id, u.number,
    w.time_checked, w.check_type, w.username 
    from people p inner join units u on p.id = u.resident
    left join wellness w on p.id = w.people_id 
    left outer join wellness as w2 ON w.people_id = w2.people_id
    and w.time_checked < w2.time_checked
    where w2.people_id is null and w.time_checked  < (NOW() - INTERVAL 2 DAY)
order by w.time_checked asc

【讨论】:

  • 感谢@Stephen O'Flynn!
【解决方案2】:

恕我直言,RIGHT JOINpeoplewellness 是没有意义的,因为不应该出现wellness 中有一个人但people 表中没有那个人的情况。但反之亦然。您有一个新人,但还没有关于他或她的任何健康信息。

话虽如此,您的查询可能看起来像这样

SELECT z.wellness_id, p.id, z.time_checked, z.check_type, z.username 
  FROM people p JOIN units u
    ON p.id = u.resident  LEFT JOIN
(
  SELECT w.*
    FROM
  (
    SELECT people_id, MAX(time_checked) time_checked
      FROM wellness
     GROUP BY people_id
  ) q JOIN wellness w 
      ON q.people_id = w.people_id
     AND q.time_checked = w.time_checked
) z 
    ON p.id = z.people_id
 WHERE COALESCE(time_checked, 0) < CURDATE() - INTERVAL 2 DAY

这里是SQLFiddle演示

【讨论】:

  • 老实说,我还不是 100% 的加入,我只知道我在使用它,因为它没有向我抛出任何 NULL 值。但是,您的查询确实如此,但我无法告诉您原因
  • 我不知道这是否重要,但我将right join 替换为left join,结果保持不变。
  • @jmd9qs 我提供的 sqlfiddle 示例模拟了当您在人员表中有一个人但没有关于他/她的健康检查信息的情况(至少现在)。现在根据您的要求和常识,这些记录应该在结果集中,因为还没有人检查这些人。在我的示例中,这些是 id 为 1 和 3 的人。如果您将左连接更改为内连接,您将看不到这些记录。
  • 您是对的,感谢您的意见。我从来没有提到它,但我已经提前计划好了,任何时候一个人被添加到people,他们也会被添加到wellness,这可能就是它让我感到困惑的原因。
  • 我会用你的答案作为答案,因为我从未给出过警告。谢谢!
猜你喜欢
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 2014-02-06
  • 1970-01-01
  • 2014-03-10
  • 2012-08-08
  • 2011-10-19
  • 2023-02-11
相关资源
最近更新 更多