从 LEFT JOIN 中选择最大的行

Posted

技术标签:

【中文标题】从 LEFT JOIN 中选择最大的行【英文标题】:SELECT biggest row from a LEFT JOIN 【发布时间】:2011-04-26 18:36:10 【问题描述】:

我有一个 LEFT JOIN 将表加入其中的 SQL 查询。这会导致主表中的行重复,但与 JOINed 表中的行不同。如何仅从 JOINed 表中选择日期最高的行。

这是一个例子(这是我查询的结果):

ID    Message    Date
---------------------------
0     Hi         2011-01-01
0     Bye        2011-02-05
0     Hello      2011-04-20
1     Test       2010-12-31
1     Testing    2010-11-15
2     Something  2010-12-12
2     Nothing    2011-01-01
2     Yes        2010-02-05
3     Cool       NULL

我希望每个 ID 有一行,即 ID 最高的行。

ID    Message    Date
---------------------------
0     Hello      2011-04-20
1     Test       2010-12-31
2     Nothing    2011-01-01
3     Cool       NULL

我当前的查询是这样的(我只是编造的,但它与真实的相似):

SELECT t1.ID, t2.Message, t2.Date
FROM t1
LEFT JOIN (
  SELECT t3.ID, t3.message, t3.Date
  FROM t3
  LEFT JOIN t4 ON t4.userID = 12 AND t3.ID = t4.ID
  WHERE t4.color = 'blue'
) AS t2
ON t1.ID = t2.ID
WHERE t1.userID = 12

我想我可以使用 php 并循环遍历结果并挑选出我想要的结果,但是我可以让 mysql 为我做这件事吗?

编辑:抱歉,我的第一个示例方式错了,这更像是我想要的。

编辑 2:我尝试使用 GROUP BY 和 MAX,但我认为我做错了什么。

我试过了:

SELECT t1.ID, t2.Message, MAX(t2.Date)
FROM t1
LEFT JOIN (
  SELECT t3.ID, t3.message, t3.Date
  FROM t3
  LEFT JOIN t4 ON t4.userID = 12 AND t3.ID = t4.ID
  WHERE t4.color = 'blue'
) AS t2
ON t1.ID = t2.ID
WHERE t1.userID = 12
GROUP BY t1.ID

但是,这给了我:

ID    Message    Date
---------------------------
0     Hi         2011-04-20
1     Test       2010-12-31
2     Something  2011-01-01
3     Cool       NULL

如何获取与最高日期相关的消息。

【问题讨论】:

在内部查询中,在 Id 上放置一个 group by 并选择 max date .... 我很难遵循这个例子,但看起来你的思路是正确的。可能会写一个更长的帖子,但你能把一些表结构/示例数据放在一起吗? @Rocket - t3.Id 是 t3 的主键还是纯粹是 t1 表的外键? 如果我正确阅读了这个查询,那么对于 T1 表中的 0 id,我们有 3 条不同的消息? @Rocket - 是的,但是名为ID 的列是外键而不是主键并不直观。我对这种情况的第一个想法是 t1t3 之间存在 1:1 的关系,而不是 1:Many。 【参考方案1】:
Select t1.id, t1.Message, t3.date
From t1
    Left Join t3
        On t3.id = t1.id
            And t3.id = (
                        Select Max( t3_1.Id )
                        From t3 As t3_1
                        Where t3_1.id = t3.id
                        Having Max( t3_1.date ) = t3.date
                        )
Where t1.userID = 12

据我所知,t4 的连接在查询中没有任何作用。它不会过滤结果,也不会来自 Select 子句中显示的 t4 表中的任何内容。此外,我假设t3.id 列实际上是t1 表的外键,而不是主键。如果是主键,则不需要其他最大日期过滤器。


更新给定的问题修订

通过向 t4 的 Where 子句添加条件,您已有效地将其转换为内连接。不过,一种解决方案是:

Select t1.id, t3.Message, t3.date
From t1
    Left Join t3
        On t3.id = t1.id
            And t3.id = (
                        Select Max( t3_1.Id )
                        From t3 As t3_1
                            Join t4
                                On t4.id = t3_1.id
                        Where t4.color = 'blue'
                            And t3_1.id = t3.id
                        Having Max( t3_1.date ) = t3.date
                        )
Where t1.userID = 12

【讨论】:

现在检查问题,我完全写错了,这个例子更像我现在想要的。【参考方案2】:

像这样:

SELECT 
   t1.ID, 
   t1.Message, 
   MAX(t2.Date) as [Date]
FROM t1
  LEFT JOIN (
    SELECT t3.ID, t3.Date
    FROM t3
    LEFT JOIN t4 ON t4.userID = 12 AND t3.ID = t4.ID
    WHERE t3.color = 'blue'
 ) AS t2
 ON t1.ID = t2.ID
 WHERE t1.userID = 12
 GROUP BY t1.ID, t1.Message

您可以使用GROUP BY 对某些值进行分组,但您必须对选择列表中的所有值进行分组,除非它是一个聚合函数,比如MAX

【讨论】:

谢谢,这确实有效,但我意识到我的问题是错误的。我修复了我的示例,所以这不再有效。 我实际上设法通过在子查询中使用 GROUP BY 和 ORDER BY 来解决它

以上是关于从 LEFT JOIN 中选择最大的行的主要内容,如果未能解决你的问题,请参考以下文章

在 MySQL 和 PHP 中使用多表和 LEFT JOIN 查询非常慢

MYSQL - 仅当 LEFT JOIN 中的行不存在时才选择

如何从计数中选择具有最大产生值的行

如何从Oracle中的另一个子查询中选择具有最大列的行

Redshift中的ROW_NUMBER()从每个组中选择最大的行?

SQL根据一列中的最大值从多列中选择不同的行