[英]MySQL - using results of multiple subqueries with un-matching numbers of rows
[英]MySQL - Select un-matching data in a one to many relationship
首先,这个问题是关于PHP和MySQL的
我有两个数据库表:
People
表:
person_id | field_1 | field_2 | other_fields...
和Notes
表:
note_id | person_id | created_timestamp | other_fields...
People
表与Notes
表具有一对多关系...
每次在Notes
表中创建一个Notes
,都会为其附加一个时间戳,并分配一个person_id
外键。
现在...
我需要找到所有people
谁没有过一note
对他们在过去的30天。
我现在的方式是:
person_id
和created_timestamp
> 'time(31*86400)'
从Notes
表中获取所有笔记( person_id
。我知道,但适合我的需要) person_id
添加到临时数组$temp
People
表中获取所有记录 $temp
对person_id
进行in_array()
比较 这不是很有效,并且在有很多People
或Notes
时会破坏应用程序。
有谁对此有更好的解决方案。 理想情况下,仅使用一个SQL查询就可以实现。
谢谢看
SELECT person_id FROM People WHERE person_id NOT IN
(SELECT person_id FROM Note
WHERE created_timestamp > DATE_SUB(CURDATE(), INTERVAL 30 DAY))
假定create_timestamp的类型为“ DATE”,“ TIMESTAMP”或“ DATETIME”。 如果您在此处使用unix时间戳,请使用FROM_UNIXTIME(created_timestamp)
将其转换为MySQL时间戳。
标准解决方案是使用这种形式的子查询:
Select * from people where PersonID NOT in
(select PersonID from Notes where Created_Timestamp>...)
另一种选择是在Notes上进行右外部联接,并仅对Notes.PersonID IS NULL进行过滤,这只会为您提供在Notes上不匹配的行。
就我个人而言,我更喜欢上面的子查询方法,该方法应该可以高效运行,并且比外部联接解决方案更容易理解。
我相信这应该有效:
SELECT * FROM不在person_id中的人(从注释中选择DISTINCT person_id);
如果这很关键,则可以考虑进行非规范化:将最后一个音符的时间戳存储在用户表中,并对该列建立索引。
否则,无法避免遍历整个人员表,因此请在注释表的(person_id,timestamp)对上添加索引,并使用左联接或子查询:
SELECT * FROM people
LEFT JOIN notes ON people.person_id = notes.person_id
AND notes.created_timestamp < NOW() - INTERVAL 30 DAY
WHERE notes.person_id IS NULL
SELECT * FROM people
WHERE person_id NOT IN (SELECT person_id FROM notes
WHERE created_timestamp < NOW() - INTERVAL 30 DAY)
SELECT p.*
FROM PEOPLE p
LEFT JOIN NOTES n ON n.person_id = p.person_id
AND n.created_timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY)
WHERE n.note_id IS NULL
SELECT p.*
FROM PEOPLE p
WHERE NOT EXISTS(SELECT NULL
FROM NOTES n
WHERE n.person_id = p.person_id
AND n.created_timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY))
SELECT p.*
FROM PEOPLE p
WHERE p.person_id NOT (SELECT n.person_id
FROM NOTES n
WHERE n.created_timestamp >= DATE_SUB(NOW(), INTERVAL 30 DAY))
当比较的列不可为空时,LEFT JOIN IS NULL在MySQL上效率最高 。 如果比较的列可以为空,则NOT IN和NOT EXISTS更为有效 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.