需要根据相对于同一列/表中其他日期的日期过滤MySQL结果

时间:2011-02-25 16:39:25

标签: php mysql

我有一个具有以下结构的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中执行此操作的方法。

感谢您的帮助。

3 个答案:

答案 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);