我有一个具有以下结构的MySQL表:
ID (int) (PK)
PersonID (int)
EventDate (date)
我需要做的是在另一个EventDate的14天内检索所有有一个EventDate的PersonID。
Sample Data:
ID PersonID EventDate
1 101 2011-01-01
2 102 2011-02-01
3 103 2011-03-01
4 104 2011-04-01
5 105 2011-04-11
6 106 2011-04-21
7 107 2011-05-01
8 108 2011-06-01
9 109 2011-07-01
10 110 2011-08-01
Desired Results:
104
105
106
107
我无法找到解决这个问题的方法。
我可以在PHP中完成它,但更喜欢直接在MySQL中执行此操作的方法。
感谢您的帮助。
答案 0 :(得分:2)
我相信它应该适合你
// #1 - quite slow
SELECT a.PersonID,
(SELECT COUNT(*)
FROM table1 b WHERE b.ID != a.ID
AND a.EventDate BETWEEN
(b.EventDate - INTERVAL 14 DAY AND b.EventDate + INTERVAL 14 DAY)
) as cnt
FROM table1 a
HAVING cnt >0
// or #2 - should be much faster
SELECT DISTINCT a.PersonID
FROM table1 a
INNER JOIN table1 b ON (b.ID != a.ID AND a.EventDate BETWEEN
(b.EventDate - INTERVAL 14 DAY AND b.EventDate + INTERVAL 14 DAY))
答案 1 :(得分:1)
这很接近:
SELECT DISTINCT parent.PersonID, child.PersonID, DATEDIFF(parent.EventDate, child.EventDate) AS diff
FROM testdata AS parent
JOIN testdata AS child ON ABS(DATEDIFF(parent.EventDate, child.EventDate)) < 14
WHERE (parent.personID <> child.personID)
使用
mysql> select * from testdata;
+------+----------+---------------------+
| ID | PersonID | EventDate |
+------+----------+---------------------+
| 1 | 101 | 2011-01-01 00:00:00 |
| 2 | 102 | 2011-02-01 00:00:00 |
| 3 | 103 | 2011-03-01 00:00:00 |
| 4 | 104 | 2011-04-01 00:00:00 |
| 5 | 105 | 2011-04-11 00:00:00 |
| 6 | 106 | 2011-04-21 00:00:00 |
| 7 | 107 | 2011-05-01 00:00:00 |
| 8 | 108 | 2011-06-01 00:00:00 |
| 9 | 109 | 2011-07-01 00:00:00 |
| 10 | 110 | 2011-08-01 00:00:00 |
+------+----------+---------------------+
10 rows in set (0.00 sec)
mysql> SELECT DISTINCT parent.PersonID, child.PersonID, DATEDIFF(parent.EventDate, child.EventDate) AS diff FROM testdata AS parent JOIN testdata AS child ON ABS(DATEDIFF(parent.EventDate, child.EventDate)) < 14 WHERE (parent.personID <> child.personID);
+----------+----------+------+
| PersonID | PersonID | diff |
+----------+----------+------+
| 105 | 104 | 10 |
| 104 | 105 | -10 |
| 106 | 105 | 10 |
| 105 | 106 | -10 |
| 107 | 106 | 10 |
| 106 | 107 | -10 |
+----------+----------+------+
6 rows in set (0.00 sec)
mysql>
现在的缺点是它看到105/104与104/105不同(它们是,但仅仅是彼此的镜像)。
答案 2 :(得分:0)
在PHP中,您可以这样做:
$data = array(...); // fetched data
$result = array();
$tmp = array();
foreach ( $data as $row ) {
$timestamp = strtotime($row['EventDate']);
$tmp[ $timestamp ] = $row;
}
ksort($tmp);
$prevRow = array();
$prevTimestamp = 0;
$diff = 60 * 60 * 24 * 14; // 14 days
$prevMatched = true;
foreach ( $tmp as $timestamp => $row ) {
if ( empty($prevTimestamp) ) {
$prevRow = $row;
$prevTimestamp = $timestamp;
continue;
}
if ( ( $timestamp - $prevTimestamp ) <= $diff ) {
$result[] = $row;
$prevMatched = true;
} else {
if ( $prevMatched ) {
$result[] = $prevRow;
}
$prevMatched = false;
}
}
var_dump($result);