如何从两个不同的、不相关的表中获取最新的行,并将它们合并到一个结果集中?

Posted

技术标签:

【中文标题】如何从两个不同的、不相关的表中获取最新的行,并将它们合并到一个结果集中?【英文标题】:How can I get the most recent rows from two different, unrelated tables, and merge them into one result set? 【发布时间】:2015-03-22 12:05:28 【问题描述】:

我有两个不同的表,它们的架构如下:

表1:

COLUMN_NAME     COLUMN_TYPE

campaign_id     varchar(50)
subscriber_id   varchar(50)
message         varchar(21000)
log_time        datetime
log_type        varchar(50)
level           varchar(50)
campaign_name   varchar(500)

表2:

COLUMN_NAME      COLUMN_TYPE

guid             varchar(100)
sid              varchar(100)
url              varchar(2500)
ip               varchar(20)
is_new           varchar(20)
ref              varchar(2500)
user_agent       varchar(255)
stats_time       datetime
country          varchar(50)
region           varchar(50)
city             varchar(50)
city_lat_long    varchar(50)
email            varchar(100)

我需要一个表,它是这两个表(不是所有列)的合并表,并且应该根据时间(表 1 中的 log_time 和表 2 中的 stats_time)对行进行排序。这两个表之间没有关系。

Table1 我需要的列是

campaign_id
subscriber_id
message
log_time
log_type
campaign_name

我需要的 Table2 的列是:

url
stats_time
email

我可以得到更优化的解决方案吗?

查询:

SELECT url, ip, stats_time, email, campaign_id, subscriber_id, campaign_name, log_time, log_type, time from
(  
( SELECT url,ip,stats_time,email,NULL AS campaign_id,NULL AS subscriber_id ,NULL AS campaign_name,NULL AS log_time,NULL AS log_type, NULL AS message, UNIX_TIMESTAMP(stats_time) AS time FROM Tabel2 AS Table2Alias WHERE URL !='' AND EMAIL != '') Order by stats_time desc Limit 100

UNION ALL  

( SELECT NULL AS url,NULL AS ip,NULL AS stats_time,NULL AS email,campaign_id,subscriber_id,campaign_name,log_time,log_type,message,UNIX_TIMESTAMP(log_time) AS time FROM Table1 AS Table1Alias WHERE (log_type='x1' OR log_type='x2' OR log_type='x3' OR log_type='x4') order by log_time desc Limit 100)
)
as ResultTable order by time  desc

【问题讨论】:

先联合起来再按时间排序一次不是更快吗? 没有。桌子太大了。并且有一个向下滚动功能可以触发带有偏移量和限制的查询。因此,每当有滚动时,每次合并两个表并不快。 这样做的目的是什么?你想提取什么信息? 我需要这两个表中最近的 20 行。他们没有任何共同点。但是有一个时间列,我可以通过它获取最近的 20 行。 如果你只想要表组合中最近的 20 行,那么为什么要让它们返回 100 行,每行都带有 LIMIT?如果总共只需要 20 个,则每个只需要 20 个,然后您可以从这 40 个结果中选择最近的 20 个。 【参考方案1】:

给你一些伪代码 -

 SELECT 
     /* columns you want */ 
 FROM 
     (
         SELECT 
             /* columns you want */
         FROM
             /* Table1 */ 
         ORDER BY 
             /* Date DESC */
         LIMIT 20 

         UNION ALL 

         SELECT 
             /* columns you want */
         FROM
             /* Table2 */ 
         ORDER BY 
             /* Date DESC */
         LIMIT 20 
    ) 
ORDER BY 
     /* Date DESC */
LIMIT 20

【讨论】:

您好,此查询不适用于一种情况。如果 table1 在今天有 60 行,而 table 2 在昨天有 20 行,则此查询将给出结果集,其中也将有 table2 行。这不应该是结果,因为所有前 20 行都应该来自 table1,因为它们是最新的。 你试过这个发现是这样吗?我向你保证,它不会包含来自table2 的任何内容。 ORDER BY /* Date DESC */ 后跟LIMIT 20 意味着它只会在订购后将列表中的“前”20 名。因此,如果来自 table1 的 20 个都比来自 table2 的 20 个更新,它只会显示 table1 行...【参考方案2】:

从每个表中选择最前面的Limit + Offset 记录,对结果进行UNION,然后从UNION 中进行选择。

因此,如果用户正在查看第 5 页,并且每页有 20 个项目,您将从每个表中选择前 100 条,执行 UNION,然后从结果中选择 20 条记录。

【讨论】:

以上是关于如何从两个不同的、不相关的表中获取最新的行,并将它们合并到一个结果集中?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中将插入的行捕获到一个巨大的表中? [关闭]

如何组合两个查询并将数据放入一行?

MySql 的行数并插入到计数的表中

如何从更新表中获取最新状态并将其与 MySQL 中的详细信息表连接?

如何从 SQLite 中的表中选择最新的 100 个不同条目?

MySQL 从两个不同的表中获取 user_id 和密码的查询