【问题标题】:Join two tables, only use latest value of right table连接两个表,只使用右表的最新值
【发布时间】:2012-03-19 02:54:54
【问题描述】:

我正在尝试加入 2 个表,但只加入一组记录中的最新记录。

左边的桌子:

部分

  • Part.PartNum

右表:

材质

  • Material.Partnum
  • 材料.公式
  • Material.RevisionNum

修订号从“A”开始并增加。

我想通过 PartNum 加入 2 个表,但只加入右表中的最新记录。我在 SO 上看到过其他示例,但很难将它们放在一起。

编辑:

我发现第一个修订号是“New”,然后它递增 A,B,... 永远不会超过一两个修订,所以我不担心会重复顺序。但是如何选择以“New”为第一个修订号的最新版本?

【问题讨论】:

  • 请指定您使用的 SQL Server 版本。
  • RevisionNum 怎么增加?它总是一个字符吗?如果是这样,第 27 版会发生什么?

标签: sql sql-server sql-server-2008 join


【解决方案1】:

如果 SQL Server 2005+

;WITH m AS 
(
   SELECT Partnum, Formula, RevisionNum,
     rn = ROW_NUMBER() OVER (PARTITION BY PartNum ORDER BY 
       CASE WHEN RevisionNum ='New' THEN 1 ELSE 2 END)
     FROM dbo.Material
)
SELECT p.PartNum, m.Formula, m.RevisionNum
FROM dbo.Parts AS p
INNER JOIN m ON p.PartNum = m.PartNum
WHERE m.rn = 1;

虽然很好奇,但当有超过 26 个修订版时你会怎么做(例如 Z 之后的内容)?

【讨论】:

  • 这行得通。您能花一点时间解释一下它为什么有效吗?
  • 当然它不再起作用了。你改变了问题。我已经更新了,但是如果您提前说明完整的问题,将来您可能会为人们节省大量工作和返工。
  • 至于它是如何工作的,我在这里做了一个简单的解释。它引用了不同的列,但概念是相同的。 stackoverflow.com/questions/9495699/…
【解决方案2】:

运行它的一般 SQL 语句是:

select P.PartNum, M.Formula, M.RevisionNum
from Parts P
join Material M on P.PartNum = M.PartNum
where M.RevisionNum = (select max(M2.RevisionNum) from Material M2
                       where M2.PartNum = P.PartNum);

重复上述关于修订 #26 之后发生的情况的警告。根据 #26 之后发生的情况,max(RevisionNum) 可能会中断。


编辑:

如果 RevisionNum 序列总是以 NEW 开头,然后继续 A、B、C 等,那么 max() 需要替换为更复杂(和混乱)的东西:

select P.PartNum, M.RevisionNum
from Parts P
join Material M on P.PartNum = M.PartNum
where (
      (select count(*) from Material M2 
              where M2.PartNum = P.PartNum) > 1
      and M.RevisionNum = (select max(M3.RevisionNum) from Material M3
                   where M3.PartNum = P.PartNum and M3.RevisionNum <> 'NEW')
      )
      or ( 
      (select count(*) from Material M4
              where M4.PartNum = P.PartNum) = 1
       and M.RevisionNum = 'NEW'
      )

必须有更好的方法来做到这一点。这虽然可行——但必须考虑更快的解决方案。

SQL 小提琴:http://sqlfiddle.com/#!3/70c19/3

【讨论】:

  • 见补充。很乱——我在想一定有更好的方法——也许我会在午餐时想到它!
【解决方案3】:

SQL Server 2005+ 也是如此:

更新以处理 OP 不断变化的要求

SELECT P.PartNum,
       M.Formula,
       M.RevisionNum
FROM Part AS P
CROSS APPLY (
    SELECT TOP 1 *
    FROM Material AS M
    WHERE M.Partnum = P.PartNum
    ORDER BY CASE WHEN RevisionNum ='New' THEN 2 ELSE 1 END,
             M.RevisionNum DESC
) AS M

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 2014-08-12
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    相关资源
    最近更新 更多