Php 通过UNION group按给定字段连接2个表,并仅获取组中最新的表
我正在一个小仪表板中构建一个电子邮件收件箱。是使用其他API的自定义电子邮件客户端。我准备DB结构的方式如下: 输入的Php 通过UNION group按给定字段连接2个表,并仅获取组中最新的表,php,mysql,sql,Php,Mysql,Sql,我正在一个小仪表板中构建一个电子邮件收件箱。是使用其他API的自定义电子邮件客户端。我准备DB结构的方式如下: 输入的表 ╔════╦════════════════════╦═══════════════════╦═════════════════════════════════════════╦══════════════════════╗ ║ id ║ email_from ║ email_to ║ email_body
表
╔════╦════════════════════╦═══════════════════╦═════════════════════════════════════════╦══════════════════════╗
║ id ║ email_from ║ email_to ║ email_body ║ date ║
╠════╬════════════════════╬═══════════════════╬═════════════════════════════════════════╬══════════════════════╣
║ 1 ║ stack@overflow.com ║ mitch@example.com ║ Your question has a downvote for newbie ║ 2017-12-28T00:00:00Z ║
║ 2 ║ stack@exchange.com ║ mitch@example.com ║ You gotta learn SQL, buddy :/ ║ 2017-12-28T00:01:43Z ║
║ 3 ║ stack@overflow.com ║ mitch@example.com ║ Guess what? 42 ║ 2017-12-28T00:05:00Z ║
║ 3 ║ stack@overflow.com ║ mitch@example.com ║ This is a bot, stop responding ║ 2017-12-28T00:10:00Z ║
╚════╩════════════════════╩═══════════════════╩═════════════════════════════════════════╩══════════════════════╝
╔════╦═══════════════════╦════════════════════╦════════════════════════════════════╦══════════════════════╗
║ id ║ email_from ║ email_to ║ email_body ║ date ║
╠════╬═══════════════════╬════════════════════╬════════════════════════════════════╬══════════════════════╣
║ 1 ║ mitch@example.com ║ stack@overflow.com ║ That is bad news ║ 2017-12-28T00:00:50Z ║
║ 2 ║ mitch@example.com ║ stack@exchange.com ║ I know :( ║ 2017-12-28T00:01:45Z ║
║ 3 ║ mitch@example.com ║ stack@overflow.com ║ Answer to the Ultimate Question... ║ 2017-12-28T00:07:42Z ║
╚════╩═══════════════════╩════════════════════╩════════════════════════════════════╩══════════════════════╝
导出的表
╔════╦════════════════════╦═══════════════════╦═════════════════════════════════════════╦══════════════════════╗
║ id ║ email_from ║ email_to ║ email_body ║ date ║
╠════╬════════════════════╬═══════════════════╬═════════════════════════════════════════╬══════════════════════╣
║ 1 ║ stack@overflow.com ║ mitch@example.com ║ Your question has a downvote for newbie ║ 2017-12-28T00:00:00Z ║
║ 2 ║ stack@exchange.com ║ mitch@example.com ║ You gotta learn SQL, buddy :/ ║ 2017-12-28T00:01:43Z ║
║ 3 ║ stack@overflow.com ║ mitch@example.com ║ Guess what? 42 ║ 2017-12-28T00:05:00Z ║
║ 3 ║ stack@overflow.com ║ mitch@example.com ║ This is a bot, stop responding ║ 2017-12-28T00:10:00Z ║
╚════╩════════════════════╩═══════════════════╩═════════════════════════════════════════╩══════════════════════╝
╔════╦═══════════════════╦════════════════════╦════════════════════════════════════╦══════════════════════╗
║ id ║ email_from ║ email_to ║ email_body ║ date ║
╠════╬═══════════════════╬════════════════════╬════════════════════════════════════╬══════════════════════╣
║ 1 ║ mitch@example.com ║ stack@overflow.com ║ That is bad news ║ 2017-12-28T00:00:50Z ║
║ 2 ║ mitch@example.com ║ stack@exchange.com ║ I know :( ║ 2017-12-28T00:01:45Z ║
║ 3 ║ mitch@example.com ║ stack@overflow.com ║ Answer to the Ultimate Question... ║ 2017-12-28T00:07:42Z ║
╚════╩═══════════════════╩════════════════════╩════════════════════════════════════╩══════════════════════╝
所以,我想做一个类似Gmail的小收件箱,在这里你可以看到所有电子邮件的列表,按电子邮件地址(或对话)分组,按日期排序,在顶部显示最新消息,在每个对话中,只显示该对话的最后一条消息
我的查询尝试
SELECT `email_from` as `thread_email`, `email_body`, `date`
FROM (
SELECT `email_from`, `email_body`, `date` FROM `incoming`
UNION
SELECT `email_to` as `email_from`, `email_body`, `date` FROM `outgoing`
) AS t_union
GROUP BY `email_from`
ORDER BY `date` DESC
结果:
╔════════════════════╦═════════════════════════════════════════╦══════════════════════╗
║ thread_email ║ email_body ║ date ║
╠════════════════════╬═════════════════════════════════════════╬══════════════════════╣
║ stack@exchange.com ║ You gotta learn SQL, buddy :/ ║ 2017-12-28T00:01:43Z ║
║ stack@overflow.com ║ Your question has a downvote for newbie ║ 2017-12-28T00:00:00Z ║
╚════════════════════╩═════════════════════════════════════════╩══════════════════════╝
它仅显示来自传入表的结果
我的预期结果
SELECT `email_from` as `thread_email`, `email_body`, `date`
FROM (
SELECT `email_from`, `email_body`, `date` FROM `incoming`
UNION
SELECT `email_to` as `email_from`, `email_body`, `date` FROM `outgoing`
) AS t_union
GROUP BY `email_from`
ORDER BY `date` DESC
- 按电子邮件地址分组,这表示对话(称为
thread\u email
,基本上每个thread\u email
一行)
- 每行(或对话,或
thread\u email
)仅显示该thread\u email
的最新消息(最后一条消息可能是传入的或传出的)
- 按日期排序(最近的第一个)
SQL Fiddle:
这是实现这一目标的新手方式吗?对另一种数据库结构有什么建议,这种结构更简单,但也更干净和有序吗?正如Gordon所说,如果group by
您的数据减少到一行,但如果您只使用order by
子句,您仍然会得到重复的数据,它将从union表中获取所有数据
groupby
子句也有一个having
子句,但它似乎只适用于数字,比如count(*)>2
和其他内容
在中,我们有一个叫做数组\u agg
的东西,它将一些数据转换成数组,然后我们可以作为数组访问它
在MySQL中,我发现的唯一相似之处是,使用与“,”连接的字符串中相同的grouped by语句转换所有数据,因此,idk如果这可以解决您的问题,但您可以尝试在应用程序端处理结果,而不是在SQL端处理
您可以这样使用:
select email_from, group_concat(email_body), date from (
select email_from, email_body, date from incoming union all
select email_to as email_from, email_body, date from outgoing
) as t_union group by email_from order by date desc;
或者,在最后一种情况下,以非优化的方式:
select email_from, email_body, date from (
select email_from, email_body, date from incoming union all
select email_to as email_from, email_body, date from outgoing
) as t_union_1 where date in (
select max(date) from (
select email_from, email_body, date from incoming union all
select email_to as email_from, email_body, date from outgoing
) as t_union group by email_from order by date desc
);
为什么要用两个表而不是一个表呢?不完全是,我正在尽可能有条理地构建这个web应用程序。此外,我发现这种基于2表的结构更容易构建特定的对话页面(我的问题是构建对话的主索引)。你对改善我目前的结构有什么建议吗?非常感谢您的帮助:)最后一个案例似乎如预期的那样有效。我希望它能以10000张唱片表现出色。谢谢你,马克西米利安!