如何将一个表中的最近一行join到另一个表中?

我有这样的数据:

entities id name 1 Apple 2 Orange 3 Banana 

定期地,一个过程将运行并给每个实体一个分数。 该过程生成数据并将其添加到分数表中,如下所示:

 scores id entity_id score date_added 1 1 10 1/2/09 2 2 10 1/2/09 3 1 15 1/3/09 4 2 10 1/03/09 5 1 15 1/4/09 6 2 15 1/4/09 7 3 22 1/4/09 

我希望能够select所有的实体以及最近logging的分数,从而得到如下的一些数据:

 entities id name score date_added 1 Apple 15 1/4/09 2 Orange 15 1/4/09 3 Banana 15 1/4/09 

我可以使用此查询获取单个实体的数据:

 SELECT entities.*, scores.score, scores.date_added FROM entities INNER JOIN scores ON entities.id = scores.entity_id WHERE entities.id = ? ORDER BY scores.date_added DESC LIMIT 1 

但是我不知道如何为所有实体select相同的东西。 也许它正在盯着我呢?

非常感谢您花时间。

谢谢你的回应。 我会给它几天,看看是否有一个首选的解决scheme泡沫,然后我会select答案。

更新:我尝试了几个build议的解决scheme,我现在面临的主要问题是,如果一个实体还没有生成的分数,他们不会出现在列表中。

SQL看起来像什么来确保所有实体都返回,即使他们还没有发布任何分数?

更新:select答案。 感谢大家!

我这样做:

 SELECT e.*, s1.score, s1.date_added FROM entities e INNER JOIN scores s1 ON (e.id = s1.entity_id) LEFT OUTER JOIN scores s2 ON (e.id = s2.entity_id AND s1.id < s2.id) WHERE s2.id IS NULL; 

只是为了添加我的变化:

 SELECT e.*, s1.score FROM entities e INNER JOIN score s1 ON e.id = s1.entity_id WHERE NOT EXISTS ( SELECT 1 FROM score s2 WHERE s2.id > s1.id ) 

方法1

 SELECT entities.*, scores.score, scores.date_added FROM entities INNER JOIN scores ON entities.id = scores.entity_id WHERE scores.date_added = (SELECT max(date_added) FROM scores where entity_id = entities.id) 

方法2

查询与批次相关的成本:

  • 方法1 :22% – 更快

  • 方法2:22% – 更快

  • 方法3 :27%

  • 方法4 :27%


 SELECT entities.*, scores.score, scores.date_added FROM entities INNER JOIN scores ON entities.id = scores.entity_id inner join ( SELECT entity_id, max(date_added) as recent_date FROM scores group by entity_id ) as y on entities.id = y.entity_id and scores.date_added = y.recent_date 

我知道这是一个老问题,只是认为我会添加一个没有人提到的方法,即Cross ApplyOuter Apply 。 这些在SQL Server 2005中可用(数据库types在此问题中未被标记)或更高

使用临时表

 DECLARE @Entities TABLE(Id INT PRIMARY KEY, name NVARCHAR(MAX)) INSERT INTO @Entities VALUES (1, 'Apple'), (2, 'Orange'), (3, 'Banana'), (4, 'Cherry') DECLARE @Scores TABLE(Id INT PRIMARY KEY, Entity_Id INT, Score INT, Date_Added DATE) INSERT INTO @Scores VALUES (1,1,10,'2009-02-01'), (2,2,10,'2009-02-01'), (3,1,15,'2009-02-01'), (4,2,10,'2009-03-01'), (5,1,15,'2009-04-01'), (6,2,15,'2009-04-01'), (7,3,22,'2009-04-01') 

你可以使用

 SELECT E.Id, E.name, S.Score, S.Date_Added FROM @Entities E CROSS APPLY ( SELECT TOP 1 * FROM @Scores Sc WHERE Sc.Entity_Id = E.Id ORDER BY sc.Score DESC ) AS S 

得到期望的结果。 equivilent允许没有分数的实体将是

 SELECT E.Id, E.name, S.Score, S.Date_Added FROM @Entities E OUTER APPLY ( SELECT TOP 1 * FROM @Scores Sc WHERE Sc.Entity_Id = E.Id ORDER BY sc.Score DESC ) AS S 
 SELECT entities.*, scores.score, scores.date_added FROM entities INNER JOIN scores ON entities.id = scores.entity_id WHERE entities.id in (select id from scores s2 where date_added = max(date_added) and s2.id = entities.id) ORDER BY scores.date_added DESC LIMIT 1 

您还可以在大多数RDBMS(Oracle,PostgreSQL,SQL Server)中使用窗口函数(如ROW_NUMBER)进行自然查询:

 SELECT id, name, score, date_added FROM ( SELECT e.id, e.name, s.score, s.date_added, ROW_NUMBER() OVER (PARTITION BY e.id ORDER BY s.date_added DESC) rn FROM Entities e INNER JOIN Scores s ON e.id = s.entity_id ) tmp WHERE rn = 1; 

SQL小提琴