2014-10-02 54 views
0

MySQL noob问题:使用MySQL的活动关联查询

我有两个实体“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点和13点之间#2和#3都是活跃的,等等。

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

我想开发一个查询,将返回此结果。理想情况下,这个查询将遍历整个数据库并且吐出包含一个“foo”id和一个活动重合的“bar”id的行。

作为一个起点,我想出了一个查询来识别所有这些过程中富活动的各个时期都处于活动状态栏的对象:

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

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

有什么建议吗?

+0

你能给我们一个你想要的输出应该是什么样子的例子吗? – Arun 2014-10-02 19:43:52

+0

您的查询只考虑在foo的期间开始和结束的小节。他们不能部分重叠吗? – 1010 2014-10-02 21:50:39

+0

Arun我在寻找的输出只是foo ID和匹配的条形码ID; Ollie琼斯的答案钉了它。 @ 1010不,我特别想排除所有重叠的情况。 – swarga 2014-10-03 16:19:01

回答

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

然后,你要做的是统计你拥有的不同“foo”物品的数量,并计算不同组合的数量。然后你加入他们,你会得到你想要的结果。 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 

我认为这是做你想做的。但是,如果没有更彻底的解释,很难确定。

+0

我同意。我会交换连接和左连接以包含没有酒吧的foos。 – 1010 2014-10-02 21:59:00