【问题标题】:SQL selecting most recent row inside joinSQL在连接中选择最近的行
【发布时间】:2020-05-07 08:18:23
【问题描述】:


我有 2 张桌子 companiesinvoices
我想选择所有具有最新发票价格的公司。
我似乎没有让它工作。
这是我尝试过的:

SELECT *
FROM companies H INNER JOIN
     invoices V
     ON H.company_id = V.BC_ID
WHERE V.ISCOMMISSIE = 0 AND
      V.DATE = (SELECT MAX(v2.DATE) FROM invoices v2 WHERE v2.BC_ID = V.BC_ID AND v2.ISCOMMISSIE = 0);

但查询加载时间很长,我不知道为什么。 结构如下:

公司

company_id | company_name |
   1       |   company 1  |
   2       |   company 2  | 

发票

invoice_id | BC_ID | DATE       | ISCOMMISSIE | price     |
  1        |   2   | 2020-01-01 |      0      |   340,40  |
  2        |   1   | 2020-01-11 |      0      |   240,40  |
  3        |   1   | 2020-01-08 |      0      |   250,30  |
  4        |   2   | 2020-01-18 |      0      |   150,30  |
  5        |   2   | 2020-01-19 |      1      |   150,30  |

BC_IDcompany_id 相同,ISCOMMISSIE 应为 0。
我想选择最近的日期。
有人知道如何做到这一点并尽可能快地进行查询吗? http://sqlfiddle.com/#!9/2fc3a/1

【问题讨论】:

  • 添加一些样本表数据,同时指定预期的结果。
  • 指定 MySQL 版本。是否允许横向连接?
  • @Akina 5.7.28 是版本

标签: mysql sql join max


【解决方案1】:

试试:

SELECT H.*, V.*
FROM companies H 
INNER JOIN invoices V ON H.company_id = V.BC_ID
INNER JOIN ( SELECT v2.BC_ID, MAX(v2.DATE) DATE
             FROM invoices v2
             WHERE v2.ISCOMMISSIE = 0
             GROUP BY v2.BC_ID ) v3 ON v.BC_ID = v3.BC_ID 
                                   AND v.DATE = v3.DATE
AND V.ISCOMMISSIE = 0

索引invoices (ISCOMMISSIE, BC_ID, DATE) 可能会有所帮助...

【讨论】:

  • 我试过这个查询,它可以工作而且速度更快:) 谢谢
【解决方案2】:

您的查询很好:

SELECT *
FROM companies H INNER JOIN
     invoices V
     ON H.company_id = V.BC_ID
WHERE V.ISCOMMISSIE = 0 AND
      V.DATE = (SELECT MAX(v2.DATE)
                FROM invoices v2
                WHERE v2.BC_ID = V.BC_ID AND
                      v2.ISCOMMISSIE = 0
               );

为了提高性能,您需要在invoices(BC_ID, ISCOMMISSIE, DATE) 上建立索引。

一个不错的选择是使用窗口函数:

SELECT *
FROM companies H INNER JOIN
     (SELECT V.*,
             ROW_NUMBER() OVER (PARTITION BY BC_ID ORDER BY DATE DESC) as seqnum
      FROM invoices V
      WHERE V.ISCOMMISSIE = 0
     ) V
     ON H.company_id = V.BC_ID
WHERE seqnum = 1;

【讨论】:

    【解决方案3】:

    根据您需要的列,您可能不需要加入公司表。 iscommissie = 0 也不需要测试两次,加入前在子查询中测试一次即可。

    请参阅下面的查询:

    SELECT i.*
    FROM invoices i
    JOIN (
         SELECT i.bc_id, MAX(date) AS max_date
         FROM invoices i
         WHERE iscommissie = 0
         GROUP BY i.bc_id
    ) i_temp ON i.bc_id = i_temp.bc_id AND i.date = i_temp.max_date
    

    FIND A DEMO HERE

    【讨论】:

      【解决方案4】:

      获得预期输出的另一种方法:

      select * from companies A join (
      select * from invoices where (BC_ID,DATE) in(
      select BC_ID as BC_ID, MAX(DATE) DATE from invoices where ISCOMMISSIE = 0 group by 
      BC_ID
      ))B on A.company_id=B.BC_ID;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-30
        • 2018-06-12
        • 2012-07-11
        • 1970-01-01
        • 1970-01-01
        • 2020-08-30
        • 1970-01-01
        相关资源
        最近更新 更多