连接表中的ORDER BY和LIMIT 1

时间:2013-08-17 21:19:57

标签: mysql join

我一直在努力想出这个问题,但我开始放弃了。

为简化案例,假设我有两张桌子。主表格为articles,我将其与contracts一起加入。合同表有结束日期。 我只想从每篇文章中选择一(1)行,选择最新的 contract_to 日期。

我尝试过类似LEFT JOIN contracts ON (contracts.article = articles.id) ORDER BY contract_to DESC LIMIT 1的尝试,但显然它不起作用。

我该怎么做?

请假设下面合同表中每行的日期范围不同 所有文章合同的最新日期也不尽相同,所以我不能确定最新日期是什么,然后将其粘贴到WHERE子句中。

enter image description here

3 个答案:

答案 0 :(得分:3)

要获取最新的contract_to值,您需要MAX()聚合。执行此操作的正确方法是使用子查询连接仅获取articleMAX(contract_to)值,然后将其与行的其余值连接。最后,整个结构可以与articles表连接。

SELECT
  articles.*,
  contracts.*
FROM 
  articles
  /* Join against a subquery which returns only the article and latest contract_to */
  LEFT JOIN (
    SELECT article, MAX(contract_to) AS contract_to
    FROM contracts
    GROUP BY article
  ) maxcontract ON articles.article_id = maxcontract.article
  /* and join that against the rest of the contracts table, on those two column values */
  JOIN contracts 
    ON maxcontract.article = contracts.article
    AND maxcontract.contract_to = contracts.contract_to

由于MySQL对GROUP BY子句的内容很宽松,因此实际上可能不需要此方法,单独加入contracts表,并且您可以单独使用子查询连接来执行此操作,但这在大多数其他RDBMS中都不起作用,这是真正正确的方法,而不依赖于MySQL的奇怪行为。

答案 1 :(得分:1)

MySQL没有一些DBMS为此提供的好的分析功能,但你可以编写(例如):

SELECT ...
  FROM articles
  LEFT
 OUTER
  JOIN ( SELECT article,
                MAX(contract_to) AS contract_to
           FROM contracts
          GROUP
             BY article
       ) articles_to_max_contracts
    ON articles_to_max_contracts.article = articles.id
  LEFT
 OUTER
  JOIN contracts
    ON contracts.article = articles.id
   AND contracts.contract_to = articles_to_max_contracts.contract_to
;

答案 2 :(得分:0)

要获得价格,您还可以使用相关子查询来执行此操作:

select a.*,
       (select price
        from contracts c
        where a.article = c.article
        order by contract_from desc
        limit 1
       ) as lastPrice
from articles a;

使用contracts(article, contract_from)上的索引,这甚至应该相对有效。