过滤掉连接查询中的最新行

Posted

技术标签:

【中文标题】过滤掉连接查询中的最新行【英文标题】:Filtering out most recent row in a join query 【发布时间】:2019-03-28 17:31:27 【问题描述】:

我有 2 个包含以下信息的表。不幸的是,我对 JOINS 和 mysql 的基本知识并没有帮助我实现我需要的结果集……尤其是第 3 点让我望而却步。非常感谢任何帮助。

订单

OrderID     OrderDate   Client      Country 

68349       1/1/2018    GSC Ltd     US
93909       1/1/2018    XYZ Ltd     UK
39900       3/31/2018   ABC Ltd     US
69382       4/4/2018    ABC Ltd     US
94500       6/21/2018   DEF Ltd     US
93911       1/1/2018    TUV Ltd     UK

报告

RepID   State   RepDate     Building    OrderID

1   AK  1/1/2018    PE James    93909
2   CA  4/2/2018    PE Grid     93909
3   CA  3/31/2018   PMU Jaya    39900
4   WA  4/4/2018    PMU Taman   69382
5   CA  6/21/2018   PE Grid     94500
6   CA  3/31/2018   PMU Wate    39900

我需要选择所有基于:

    选择国家/地区 = 美国的订单 选择属于这些美国订单一部分的报告(即订单 ID = 上述结果中的订单 ID) 最重要的是:过滤报告结果,使其仅显示每个建筑物的单个最新报告(基于最近的 RepDate)

所以结果是:

OrderID     OrderDate   Client      Country     RepID   RepDate     Building 

68349       1/1/2018    GSC Ltd     US      -   -       -
39900       3/31/2018   ABC Ltd     US      3   3/31/2018   PMU Jaya
69382       4/4/2018    ABC Ltd     US      4   4/4/2018    PMU Taman
94500       6/21/2018   DEF Ltd     US      5   6/21/2018   PE Grid

以下结果将被排除,因为“PE Grid”有更新的报告:

OrderID     OrderDate   Client      Country     RepID   RepDate     Building 

39900       3/31/2018   ABC Ltd     US      6   3/31/2018   PE Grid

【问题讨论】:

OrderDateRepDate 字段的数据类型是什么? 它们是日期字段。实际的表格是 YYYY-MM-DD 格式。但我只是让日期在这里更容易阅读。希望没关系。 见:Why should I provide an MCVE for what seems to me to be a very simple SQL query? 欢迎来到 Stack Overflow,@Kristy。为了将来参考,明智的做法是给您的问题一个描述性标题。它可以帮助其他有类似问题的人找到您的问题和任何答案。我冒昧地编辑了这个标题。 这是一个(很明显也很容易找到)常见问题解答。 PS 请通过编辑而不是 cmets 澄清。 【参考方案1】:

找到每个建筑物的最新报告是这里的诀窍。首先,您需要找到最新报告的日期,如下所示。

               SELECT MAX(RepDate) RepDate, Building
                 FROM reports
                GROUP BY RepDate

GROUP BY 保证每栋建筑只有一排。

然后您需要将该查询视为一个虚拟表并加入它。 (http://sqlfiddle.com/#!9/ade437e/2/0)

SELECT o.OrderID, o.OrderDate, o.Client, o.Country,
       r.RepId, r.RepDate, r.Building
  FROM orders o
  LEFT JOIN reports r ON o.OrderID = r.OrderID
  LEFT JOIN ( SELECT MAX(RepDate) RepDate, Building
                FROM reports
                GROUP BY RepDate
            ) m ON r.RepDate = m.RepDate AND r.Building = m.Building

注意这里使用了LEFT JOIN。这意味着没有匹配报告的订单仍将显示在结果集中。如果您不想要这些订单,请将LEFT JOIN 更改为JOIN

如果您想过滤该结果集,请将WHERE o.Country = 'US'(或您选择的过滤器)添加到查询的末尾。然后,您可以使用ORDER BY 对结果集进行排序,如果这是您需要的。

诀窍是从内到外构建查询。

顺便说一下,这被称为greatest n per group 模式。

【讨论】:

以上是关于过滤掉连接查询中的最新行的主要内容,如果未能解决你的问题,请参考以下文章

复杂的 SQL 连接查询 - 获取最新行

多表连接查询中,“on”和“where”有啥区别吗?

Flask-SQLAlchemy 左外连接过滤查询

无论如何,他们是不是要向使用 group by 返回特定列的最新行的查询添加连接

MySQL连接查询(多表查询)

mysql左连接没有数据还会查出来吗