使用MySQL的活动关联查询

时间:2014-10-02 19:39:46

标签: mysql

MySQL noob问题:

我有两个实体" foo"和" bar"我要关联的活动。具体来说,我想确定哪个" bar"对象在给定的" foo"的同时处于活动状态。对象

为此,我已经建立了一个包含两个表的简单MySQL数据库:

select * from foo;
+------+---------------------+---------------------+
| id   | arrive              | depart              |
+------+---------------------+---------------------+
|    1 | 2014-10-01 08:00:00 | 2014-10-01 09:00:00 |
|    1 | 2014-10-01 10:00:00 | 2014-10-01 11:00:00 |
|    1 | 2014-10-01 12:00:00 | 2014-10-01 13:00:00 |
|    2 | 2014-10-01 09:00:00 | 2014-10-01 10:00:00 |
|    2 | 2014-10-01 12:00:00 | 2014-10-01 13:00:00 |
+------+---------------------+---------------------+

select * from bar;

+------+---------------------+---------------------+
| id   | start               | end                 |
+------+---------------------+---------------------+
|    1 | 2014-10-01 08:05:00 | 2014-10-01 08:55:00 |
|    1 | 2014-10-01 09:05:00 | 2014-10-01 09:55:00 |
|    1 | 2014-10-01 11:05:00 | 2014-10-01 11:55:00 |
|    2 | 2014-10-01 11:05:00 | 2014-10-01 11:55:00 |
|    2 | 2014-10-01 12:05:00 | 2014-10-01 12:55:00 |
|    2 | 2014-10-01 07:05:00 | 2014-10-01 07:55:00 |
|    3 | 2014-10-01 08:05:00 | 2014-10-01 08:55:00 |
|    3 | 2014-10-01 10:05:00 | 2014-10-01 10:55:00 |
|    3 | 2014-10-01 12:05:00 | 2014-10-01 12:55:00 |
+------+---------------------+---------------------+

毋庸置疑,"到达"并且"开始"列表示活动期间的开始,"离开"和"结束"列表示每个句点的结尾,id列是每个对象的唯一标识符。

作为第一步,对于foo中的每个活动时段,我想确定在同一时间段内处于活动状态的一组条形对象。

从foo#1上面的示例数据中: 在8:00到9:00之间(即在foo#1的第一个活动期间),条形#1和条形#3都是活动的, 在10:00到11:00之间,只有#3栏活跃, 在12:00和13:00之间,#2栏和第3栏都是活动的等等。

一旦确定了这些集合,如果我可以确定它们的交集,我将得到我想要的答案(例如,条形#3是唯一与foo对象#1同时处于活动状态的条形对象)。

我正在尝试开发一个会返回此结果的查询。理想情况下,此查询将遍历整个数据库并吐出包含一个" foo" id和one" bar" id活动重合的地方。

作为一个起点,我提出了一个查询来识别在每个foo活动期间活动的所有条形对象:

SELECT foo.id, 
       bar.id 
FROM foo 
LEFT JOIN bar 
ON bar.start >= foo.arrive 
AND bar.end <= foo.depart;

但是,我不知道从哪里开始。一个相关的子查询似乎可能有用,但我没有太多的运气制定一个没有错误。我甚至不确定这是否是正确的做法。

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

据我所知,您的JOIN查询是正确的。它获取完全包含在(到达 - 离开)间隔内的(开始 - 结束)间隔。 JOIN是正确的选择。

在结果集中添加invervals可以更容易理解:

SELECT foo.id AS fooid, arrive, depart,
       bar.id AS barid, start, end
  FROM foo 
  LEFT JOIN bar  
              ON bar.start >= foo.arrive 
             AND bar.end <= foo.depart

这是一个SQL小提琴,显示了这一点。 http://sqlfiddle.com/#!2/68b7dc/3/0

然后,你要做的是计算不同的&#34; foo&#34;您拥有的物品,并计算不同组合的数量。然后你将它们加在一起,你就可以得到你想要的结果。 http://sqlfiddle.com/#!2/ed5ac/5/0

SELECT a.fooid, b.barid
  FROM (
      SELECT COUNT(*) AS count,
             id AS fooid
        FROM foo
       GROUP BY id
        ) AS a
   JOIN (
       SELECT COUNT(*) AS count,
              foo.id AS fooid,
              bar.id AS barid
         FROM foo 
         LEFT JOIN bar  
                    ON bar.start >= foo.arrive 
                   AND bar.end <= foo.depart
        GROUP BY foo.id, bar.id
         ) AS b ON a.count=b.count AND a.fooid = b.fooid

我认为这可以满足您的需求。但如果没有更彻底的解释,很难确定。