将一个表与另一个表的最新行连接起来

时间:2014-12-23 20:10:07

标签: mysql sql join

我有2个MySQL表,包含以下信息:

table1 (基本信息)

name | url
a    | www.a.com
b    | www.b.com
c    | www.c.com

table2 (时间序列数据)

name | status | date
a    | ok     | 22/12/14
b    | ok     | 22/12/14
c    | ok     | 22/12/14
a    | ok     | 21/12/14
b    | ok     | 21/12/14
c    | ok     | 21/12/14
etc

我需要进行连接,所以我将table1中的所有条目与table2的最新条目一起加入。所以输出看起来像:

输出

name | url       | status | date
a    | www.a.com | ok     | 22/12/14
b    | www.b.com | ok     | 22/12/14
c    | www.c.com | ok     | 22/12/14

上面的输出会有什么查询?

7 个答案:

答案 0 :(得分:2)

这是一个棘手的问题。你能做的就是两次加入第二张桌子 - 一张找到"最新的"第二次获取实际数据。

SELECT t1.name, t1.url, t2.status, t2.date
FROM table1 t1
LEFT JOIN (SELECT name, max(date) as mx from table2 GROUP BY name) as X ON X.name = t1.name
LEFT JOIN table2 t2 0N t2.name = X.name AND t2.date = X.mx

我用名字加入。您通常会使用某些键(ID)

答案 1 :(得分:1)

我专注于时间敏感的设计,这就是我的工作。您的第二个表是一个Versioned表,与源控制系统一样,当数据发生更改时,旧数据仍然存在,只需使用更改日期创建新副本。一个小的改动可以增加完整的双时间功能,但这不是你的问题,是吗? 8)

如果像我发现的那样,你注意到针对这个表的绝大多数查询是针对当前数据的,那么你可能要考虑的一件事就是创建一个视图来仅公开每个查询的当前版本行。

create view tab2 as
select *
from   table2 t2
where  date =(
    select  max( date )
    from    table2
    where   name = t2.name );

然后,您可以简单地将第一个表与视图连接,以便与table1中的数据进行一对一的关联,而只使用table2中的当前数据。这使您可以抽象出数据的时间敏感性。

如果有理由你不能使用视图(例如考虑加入视图时有癫痫发作的老派DBA)那么你必须把整个事情写成一个查询。幸运的是,这并不困难,但抽象很方便。

select t1.Name, t1.URL, t2.Status, t2.Date
from   table1 t1
join   table2 t2
  on   t2.Name = t1.Name
  and  t2.Date =(
       select  max( Date )
       from    table2
       where   name = t2.name );

某些DBMS不允许在连接中使用子查询。在这种情况下,只需将其移动到WHERE子句:

select t1.Name, t1.URL, t2.Status, t2.Date
from   table1 t1
join   table2 t2
  on   t2.Name = t1.Name
where  t2.Date =(
       select  max( Date )
       from    table2
       where   name = t2.name );

如果Name和Date形成唯一索引(显式定义或因为它们构成表的PK),您会发现性能比您最初想象的要好得多。尝试并与替代品进行比较。

答案 2 :(得分:0)

我通常在SQLServer中工作,因此您必须更正语法(如果适用),但基本上您将按可用的最大日期进行分组并仅返回这些行。请参阅下面的代码并试一试!如果这有帮助,请告诉我。

SELECT t1.name, t1.url, t2.status, max(t2.date)
FROM table1 t1
INNER JOIN table2 t2 ON t1.name = t2.name
GROUP BY t1.name, t1.url, t2.status, max(t2.date)

答案 3 :(得分:0)

试试这个,分组依据日期

SELECT  a.*,b.*
FROM    table1 a
        INNER JOIN
        (
            SELECT  table2.name name2, MAX(Date) max_date, status
            FROM    table2
            GROUP   BY name, status

        ) b ON  a.name = b.name2

答案 4 :(得分:0)

    Select t1.*, t2.status,t2.date 
    from table1 t1 inner join table t2 
    on t1.name = t2.name 
    where t2.date=(select max(date) from table2)

答案 5 :(得分:0)

没有分组或聚合的查询:

SELECT t1.name, t1.url, t21.status, t21.date
FROM table1 t1
INNER JOIN table2 t21 ON t1.name = t21.name
LEFT JOIN table2 t22 ON t21.name = t22.name AND t21.date < t22.date
WHERE t22.name IS NULL;

另一个新选择:

SELECT t1.name, t1.url, t2.status, t2.date
FROM table1 t1 INNER JOIN table2 t2 ON t1.name = t2.name
WHERE t2.date = (SELECT max(date) FROM table2 t22 WHERE t22.name = t2.name);

MySQL不支持(还有?)流行的窗口函数,它已添加到今天的大多数其他RDBMS(Oracle,SQL Server,PostgreSQL)。这是使用ROW_NUMBER编写自然的查询:

SELECT name, url, status, date from (
 SELECT t1.name, t1.url, t2.status, t2.date,
 ROW_NUMBER() OVER (PARTITION BY t1.name ORDER BY t2.date DESC) rn
 FROM table1 t1 INNER JOIN table2 t2 ON t1.name = t2.name
) tmp WHERE rn = 1;

答案 6 :(得分:-1)

SELECT t1.name, t1.url, t2.status, t2.date 
   FROM 
     table1 t1 
     JOIN table2 latest ON latest.name = t1.name 
     JOIN table2 t2 ON t2.name = latest.name AND t2.date = MAX(latest.date)
   GROUP BY t1.name, t1.url

这样做是将table2连接到自身,以便找到给定名称的最新日期。