【问题标题】:SQL server - Get newest record of joinSQL server - 获取最新的加入记录
【发布时间】:2011-01-17 16:11:52
【问题描述】:

阅读 Stackoverflow 有一段时间了,今天轮到我提问了!

表结构
它与对 SQL Server 2005 数据库的查询有关。我有以下表结构:

组件

  • 身份证

下载

  • 身份证
  • componentid(FK 到 components#id)
  • 下载日期

进口

  • 身份证
  • downloadid(FK 到 downloads#id)
  • 状态

我想得到什么
我正在尝试获取每个组件的最新下载状态。

到目前为止我在哪里
我已开始编写此查询,但我的联接运行不佳:

SELECT c.id  
FROM components as c  
JOIN (    
  SELECT componentid, MAX(downloaddate) as downloaddate, id  
  FROM downloads  
  GROUP BY componentid, id   
) d ON d.componentid = c.id  
-- JOIN on imports here...

我的问题是用于连接的查询不正确。因为我需要为连接选择 id,所以我在 group by 子句中添加了它,现在我得到了每个 componentid 的多条记录,而不是最新的一条。

如果我在连接中单独执行查询,我会得到以下结果。

componentid downloaddate            id

8882    2011-01-15 06:00:09.773 595862
8882    2011-01-16 06:00:09.847 598422
8882    2011-01-17 06:00:09.940 600971
8951    2010-11-15 03:00:22.550 450221
8951    2010-11-16 03:00:21.730 452431
8951    2010-11-17 03:00:21.920 454668
8961    2011-01-17 02:00:33.077 600532
8961    2011-01-17 02:00:59.070 600536
8983    2008-07-17 11:59:53.780 122
9005    2009-09-01 04:00:38.320 48918
9005    2009-09-02 04:00:36.260 49280

相反,我需要这样的东西:

componentid downloaddate            id

8882    2011-01-17 06:00:09.940 600971
8951    2010-11-17 03:00:21.920 454668
8961    2011-01-17 02:00:59.070 600536
8983    2008-07-17 11:59:53.780 122
9005    2009-09-02 04:00:36.260 49280

有谁知道我应该如何编写我的加入来达到预期的结果?

提前非常感谢

【问题讨论】:

  • 1个download可以关联多个imports吗?如果是这样,您需要哪个状态值?
  • 是的,一个下载有多个导入。我想获取最新导入的状态(它们也有日期)。

标签: sql sql-server join


【解决方案1】:

您无法关联 JOIN 运算符。改用 APPLY:

SELECT c.id , d.downloaddate
FROM components as c  
APPLY (    
  SELECT componentid, MAX(downloaddate) as downloaddate  
  FROM downloads  
  WHERE componentid = c.id
) as d;

其实你也可以使用 JOIN (因为内部查询实际上没有关联),但不要按 id 分组,只需按 componentid 分组:

SELECT c.id , d.downloaddate
FROM components as c  
JOIN (    
  SELECT componentid, MAX(downloaddate) as downloaddate  
  FROM downloads  
  GROUP BY componentid 
) as d ON c.id = d.componentid;

更新

SELECT *
FROM components as c  
APPLY (    
  SELECT TOP(1) componentid, downloaddate, id as downloadid
  FROM downloads  
  WHERE componentid = c.id
  ORDER BY downloaddate DESC
) as d
JOIN imports i on i.id = d.downloadid;

【讨论】:

  • 他不能把 GROUP BY 移出 JOIN 吗?并在下载表上做一个简单的连接(没有内部查询)?
  • 谢谢 Remus,你能解释一下我如何也加入导入表吗?我的问题是我必须返回下载表的 id 才能在导入时加入它。谢谢!
  • @Zunanadi:您需要按组件 ID 分组才能使用函数 MAX(downloaddate) @Remus:对不起,我无法获得您的任何解决方案来解决我的最终问题,因为他们没有允许我返回下载的 id(因为我仍然需要按 componentid 分组)
  • @user578646 - 您可以使用 ROW_NUMBER 就像 Eric 的回答一样,或者坚持使用 APPLY 但使用 TOP (1) 而不是 MAX
  • 感谢 Martin,我也可以使用 apply 和 top(1)。哪个性能最好?
【解决方案2】:

您或许可以使用 ROW_NUMBER 函数解决这个问题:

SELECT componentid, ROW_NUMBER() OVER (PARTITION BY componentid ORDER BY downloaddate DESC) as rowno
FROM downloads  
WHERE rowno = 1

【讨论】:

  • 您的解决方案有效。我在连接的子查询中添加了 ROW_NUMBER() OVER (PARTITION BY componentid ORDER BY downloaddate DESC) 作为 rowno。此外,我将 rowno=1 置于我的加入条件中,它就成功了。谢谢埃里克!
  • @user - 您也许可以完全消除子查询。 ROW_NUMBER 不需要 group by - 因此您也可以根据需要加入其他表。
  • 感谢 Eric 教我一些东西。不过,这次我将使用交叉应用,因为它似乎更适合该特定问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
  • 2012-02-12
  • 1970-01-01
  • 2018-11-16
  • 1970-01-01
  • 2015-12-17
  • 2016-10-15
相关资源
最近更新 更多