【问题标题】:Limit left join to 1将左连接限制为 1
【发布时间】:2015-06-10 11:10:33
【问题描述】:

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

这是我的代码,没有限制:

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)

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

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

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 个匹配的行,所以连接应该简单地接受它 = 查询根本没有做你想让它做的事情。 2. 查询是正确的,但有超过 1 行,您只想将其限制为 1.. 这意味着您在查询中得到的任何行都可以。

标签: mysql sql left-join limit


【解决方案1】:

首先,不要在 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 中,其他数据库做正确的事情)。而且,它们往往会阻止使用索引。

但是,您似乎想要最近的一对开始和停止。使用您的数据结构,使用joins 得到它有点痛苦。相反,对于每一行,计算给定机器/数字组合之后出现的停靠点数。然后简单地取值为“1”的行并使用条件聚合:

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;

【讨论】:

  • 第一个是等效的,但是第二个我遇到了问题。我想得到一对 start 和 stop ,其中 typ = '1' 是 stop 并且 typ = '0' 是 start 并且只有 stop 存在的结果。所以这张表应该有4个结果
  • @Alek 。 . .如果您想要两行存在的行,则添加having end_id is not null and start_id is not null
猜你喜欢
  • 1970-01-01
  • 2021-09-26
  • 2016-08-12
  • 2012-08-03
  • 1970-01-01
  • 2010-10-04
  • 2012-07-08
  • 2018-10-15
  • 1970-01-01
相关资源
最近更新 更多