从 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
的列是外键而不是主键并不直观。我对这种情况的第一个想法是 t1
和 t3
之间存在 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 中的行不存在时才选择