我有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
上面的输出会有什么查询?
答案 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连接到自身,以便找到给定名称的最新日期。