将左连接限制为1

时间:2015-06-10 11:10:33

标签: mysql sql left-join limit

我遇到了限制左连接的问题,我想要的是第一个表中的每一行只得到第二个表中的一个结果。

这是我的代码,不受限制:

SELECT * FROM
(
((SELECT id,date as end,machine_id,numer FROM `order_log` WHERE typ = 1)STOP    
left join    
(SELECT date as begin, machine_id, numer FROM `order_log` ST WHERE typ = 0 ORDER BY date DESC)START   
ON START.begin < STOP.end AND START.machine_id = STOP.machine_id 
AND START.numer = STOP.numer)
)

我也试图限制它,但后来我只得到一个正确的结果:

SELECT * FROM
(
((SELECT id,date as end,machine_id,numer FROM `order_log` WHERE typ = 1)STOP    
left join    
(SELECT date as begin, machine_id, numer FROM `order_log` ST WHERE typ = 0 ORDER BY date DESC)START   
ON START.begin = (SELECT date FROM `order_log` WHERE date < STOP.end AND typ = 0 AND machine_id = STOP.machine_id AND numer = STOP.numer ORDER BY date DESC LIMIT 1)    AND START.machine_id = STOP.machine_id 
AND START.numer = STOP.numer)
)

以下表格示例:

id  numer   machine_id  typ     date
1   31392   39          0       2015-05-26 15:44:56
2   31761   23          0       2015-05-26 16:12:53
3   31761   24          0       2015-05-26 16:14:03
4   31591   15          0       2015-05-26 16:15:02
5   31586   40          0       2015-05-26 16:15:46
6   31392   39          1       2015-05-26 16:16:19
7   31392   39          0       2015-05-26 16:16:19
8   31392   39          1       2015-05-28 08:15:26
9   31386   39          0       2015-05-28 08:15:26
10  31761   24          1       2015-06-02 00:40:07
11  31761   24          0       2015-06-02 00:40:07
12  31386   39          1       2015-06-02 13:11:13
13  31392   39          0       2015-06-02 13:11:13

预期结果:

id  end                     machine_id  numer   begin                   machine_id  numer   
6   2015-05-26 16:16:19     39          31392   2015-05-26 15:44:56     39          31392
10  2015-06-02 00:40:07     24          31761   2015-05-26 16:14:03     24          31761
8   2015-05-28 08:15:26     39          31392   2015-05-26 16:16:19     39          31392
12  2015-06-02 13:11:13     39          31386   2015-05-28 08:15:26     39          31386

提前致谢

编辑:

为了澄清,我的查询(第一个)正在运行,但它提供的结果比我想要的多,所以我只需要限制它只从左连接的第二个表中获得一行。所以来自

的每一行
(SELECT id,date as end,machine_id,numer FROM `order_log` WHERE typ = 1)

我想从

获得一行且只有一行
left join    
(SELECT date as begin, machine_id, numer FROM `order_log` ST WHERE typ = 0 ORDER BY date DESC)START   
ON START.begin = (SELECT date FROM `order_log` WHERE date < STOP.end AND typ = 0 AND machine_id = STOP.machine_id AND numer = STOP.numer ORDER BY date DESC LIMIT 1)    AND START.machine_id = STOP.machine_id 
AND START.numer = STOP.numer)

我需要获得所有现有的对,但我确信如果结束存在也开始存在,这就是我首先搜索所有typ ='1'(结束)的原因。

我现在得到的结果与预期结果比较:

2015-05-26 16:16:19     39  31392   2015-05-26 15:44:56     39  31392
2015-05-28 08:15:26     39  31392   2015-05-26 15:44:56     39  31392
2015-06-02 00:40:07     24  31761   2015-05-26 16:14:03     24  31761
2015-05-28 08:15:26     39  31392   2015-05-26 16:16:19     39  31392
2015-06-02 13:11:13     39  31386   2015-05-28 08:15:26     39  31386

第二行是不需要的

1 个答案:

答案 0 :(得分:0)

首先,不要在MySQL中使用子查询。因此,将查询写为:

SELECT s.id, s.date as end, s.machine_id, s.numer,
       o.date as begin, o.machine_id, o.numer 
FROM order_log s left join
     order_log o
     ON o.date < s.date AND o.machine_id = s.machine_id AND o.numer = s.numer
WHERE s.typ = 1 and o.typ = 0 ;

(我认为这是等价的。)子查询增加了实现的额外开销(仅在MySQL中,其他数据库做正确的事情)。并且,它们倾向于阻止使用索引。

但是,您似乎想要最近一对启动和停止。使用您的数据结构,使用join来获取此信息会有点痛苦。相反,对于每一行,计算给定机器/数字组合的之后的停靠点数。然后只需获取值为&#34; 1&#34;的行。并使用条件聚合:

select machine_id, numer,
       max(case when ol.typ = 1 then id end) as end_id,
       max(case when ol.typ = 1 then date end) as end_date,
       max(case when ol.typ = 0 then id end) as start_id,
       max(case when ol.typ = 0 then date end) as start_date
from (select ol.*,
             (select count(*)
              from order_log ol2
              where ol2.machine_id = ol.machine_id AND ol2.numer = ol.numer
             ) as grp
      from orderlog ol
     ) ol
where grp = 1
group by machine_id, numer;