MYSQL - 加入到右表PREVIOUS的最后一条记录,从左表开始记录

时间:2016-06-15 18:46:02

标签: mysql join left-join

我见过许多与此类似的问题,但并不完全像这样。 我需要做的是LEFT JOIN记录,到右表上的前一个记录。例如:

LEFT TABLE 'PROD':
idMachine |production | prod.date
1         |10         | 2016-05-02
2         |11         | 2016-05-15
3         |14         | 2016-06-01
3         |13         | 2016-06-15

RIGHT TABLE 'CONFIG':
idMachine | sett   | config.date
1         |  30    | 2016-04-01
2         |  25    | 2016-04-01
3         |  20    | 2016-04-01
1         |  40    | 2016-05-01
3         |  45    | 2016-06-10
1         |  50    | 2016-06-15

and the result should be:
idMachine |production | sett   | prod.date
1         |10         | 40     | 2016-05-02
2         |11         | 25     | 2016-05-15
3         |14         | 20     | 2016-06-01
3         |13         | 45     | 2016-06-15

系统就像这样工作,我在机器上记录所有生产运行,并且我记录每台机器配置的每一个变化,我需要知道的是它对生产运行的设置。 如果您在结果中注意到机器1和3,则不会对配置的LATEST记录进行连接,而是在生产发生之前对LAST记录进行连接,这样我们就可以知道我们使用什么设置生成了什么。

我已尝试与JOIN CONFIGS ON prod.date > config.date加入,但它加入了以前的每个配置,而不仅仅是最后一个。如果我使用LIMIT,它不会给我所需的所有记录。 我已尝试使用MAX对子查询进行一些JOINS,但子查询只返回最新的配置,而不是之前的配置,所以“旧”运行没有配置...

非常感谢任何帮助!!!

2 个答案:

答案 0 :(得分:1)

子查询还需要是两个表的JOIN,以允许您在每个PROD的CONFIG中获取前一个日期。然后再将该子查询包含在与表的连接中,以查找sett值。

这样的事情:

SELECT p2.idMachine, p2.production, c2.sett, p2.date
FROM PROD AS p2
INNER JOIN
   (SELECT p.idMachine, p.`date` AS prodDate, MAX(c.`date`) AS prev
    FROM PROD AS p 
    INNER JOIN CONFIG AS c 
       ON p.idMachine = c.idMachine AND p.`date` >= c.`date`
    GROUP BY p.idMachine, prodDate
) AS prevs
   ON p2.idMachine = prevs.idMachine AND p2.`date` = prevs.prodDate
INNER JOIN CONFIG AS c2
   ON prevs.idMachine = c2.idMachine AND prevs.prev = c2.`date`

如果你有一个WHERE子句来过滤你关心的PROD记录,你可能想把它放在子查询和主查询中......等一下......

取决于您的数据的形状"塑造"这个版本少了一个连接可以更好。

SELECT p2.idMachine, p2.production, c2.sett, p2.date
FROM (SELECT p.idMachine, p.production, p.`date`, MAX(c.`date`) AS prevConfigDate
    FROM PROD AS p 
    INNER JOIN CONFIG AS c 
       ON p.idMachine = c.idMachine AND p.`date` >= c.`date`
    GROUP BY p.idMachine, p.production, p.`date`
) AS p2
INNER JOIN CONFIG AS c2
   ON p2.idMachine = c2.idMachine AND p2.prevConfigDate = c2.`date`

但是,这里的子查询计算每个PROD的MAX,而不是每个(idMachine,date);所以它可能比额外的加入花费更多。但在这种情况下,不需要冗余的WHERE子句(子查询中只有一个副本)。

我去了...还有一个相关的子查询版本,虽然我不喜欢它们......

SELECT p.*
    , (SELECT sett 
       FROM CONFIG AS c 
       WHERE c.idMachine = p.idMachine 
          AND c.date <= p.date 
       ORDER BY c.date DESC LIMIT 1
      ) AS sett
FROM PROD AS p
;

另请注意,在所有这些中,我将日期与>=<=进行了比较,而不是<>;您可能需要根据实际数据/逻辑进行调整。

答案 1 :(得分:0)

使用您的数据和工作进行测试

SELECT *
FROM PROD
LEFT JOIN (
SELECT *
FROM `CONFIG`
GROUP BY idMachine
ORDER BY `config.date` ASC
) AS CONFIG ON PROD.idMachine = CONFIG.idMachine
WHERE `config.date` <= PROD.`prod.date` 
  

idMachine production prod.date idMachine sett config.date

     

1 10 2016-05-02 1 40 2016-05-01

     

2 11 2016-05-15 2 25 2016-04-01

     

3 14 2016-06-01 3 20 2016-04-01

     

3 13 2016-06-15 3 20 2016-04-01