2010-12-16 46 views
16

我有兩張桌子。表「B」與表「A」具有一對多關係,這意味着表「A」中的一條記錄在表「B」中將有許多記錄。加入到t-sql的「最新」記錄

表「B」的記載主要是由一個日期來區分,我需要產生一個結果,其中包括在表中的「A」加入了只有在表「B」的最新記錄備案。爲了說明目的,這裏有一個示例模式:

Table A 
------- 
ID 

Table B 
------- 
ID 
TableAID 
RowDate 

我在遇到麻煩時制定所述查詢給我我正在尋找任何幫助的結果集將不勝感激。

+0

在具有相同的datetime表B兩行的情況下,你會如何定義一個最新記錄?值得注意的是,DateTime只有3毫秒(或類似的東西),而DateTime2可以測量到納秒(所以更準確)。 – 2010-12-16 16:15:20

+0

要將[Table A]加入[Table B]的列是TableAID? – Lamak 2010-12-16 16:16:27

+0

應該包括這個......你可以假設不會有重複的日期時間,所以總會有一個「最新的」:-) – 2010-12-16 18:07:33

回答

23
select a.*, bm.MaxRowDate 
from (
    select TableAID, max(RowDate) as MaxRowDate 
    from TableB 
    group by TableAID 
) bm 
inner join TableA a on bm.TableAID = a.ID 

如果從表B需要更多的列,這樣做:

select a.*, b.* --use explicit columns rather than * here 
from (
    select TableAID, max(RowDate) as MaxRowDate 
    from TableB 
    group by TableAID 
) bm 
inner join TableB b on bm.TableA = b.TableA 
    and bm.MaxRowDate = b.MaxRowDate 
inner join TableA a on bm.TableAID = a.ID 
+0

打我幾秒:) – Randy 2010-12-16 16:14:52

+1

這並不完全回答這個問題因爲它只能從表b得到最大行數。該問題要求提供最近的一行 - 因此需要爲該行返回表b的其餘部分,並且還需要考慮表B具有兩個相同日期/時間的條目以用於TableA引用 – 2010-12-16 16:18:50

+0

@Paul:我假設表B僅由OP指定了字段。修改了查詢以處理您提到的情況。重複可能會或可能不會成爲用戶數據的問題。 – RedFilter 2010-12-16 16:22:55

3
With ABDateMap AS (
    SELECT Max(RowDate) AS LastDate, TableAID FROM TableB GROUP BY TableAID 
), 
LatestBRow As (
    SELECT MAX(ID) AS ID, TableAID FROM ABDateMap INNER JOIN TableB ON b.TableAID=a.ID AND b.RowDate = LastDate GROUP BY TableAID 
) 
SELECT columns 
FROM TableA a 
INNER JOIN LatestBRow m ON m.TableAID=a.ID 
INNER JOIN TableB b on b.ID = m.ID 
2

表B中加入是可選的:這取決於是否有其他列你想

SELECT 
    * 
FROM 
    tableA A 
    JOIN 
    tableB B ON A.ID = B.TableAID 
    JOIN 
    (
    SELECT Max(RowDate) AS MaxRowDate, TableAID 
    FROM tableB 
    GROUP BY TableAID 
    ) foo ON B.TableAID = foo.TableAID AND B.RowDate= foo.MaxRowDate 
24
SELECT * 
FROM tableA A 
OUTER APPLY (SELECT TOP 1 * 
      FROM tableB B 
      WHERE A.ID = B.TableAID 
      ORDER BY B.RowDate DESC) as B 
+1

外套更快! – 2015-05-08 01:12:50

+1

與我在我的系統上嘗試過的其他方法相比,外層應用程序非常快。 – 2016-02-29 17:12:26

+0

我剛剛測試了接受的答案和這個答案,我發現外面的應用比接受的答案慢了2倍! – Maderas 2017-03-07 16:46:16

0

只是爲了清晰起見,併爲那些將蹣跚而行的人這個古老的問題。如果在Table B中有重複的RowDate,則接受的答案將返回重複的行。更安全,更有效的方法是利用ROW_NUMBER()

Select a.*, b.* -- Use explicit column list rather than * here 
From [Table A] a 
Inner Join (-- Use Left Join if the records missing from Table B are still required 
    Select *, 
     ROW_NUMBER() OVER (PARTITION BY TableAID ORDER BY RowDate DESC) As _RowNum 
    From [Table B] 
) b 
On b.TableAID = a.ID 
Where b._RowNum = 1 
0

嘗試使用這樣的:

BEGIN 

DECLARE @TB1 AS TABLE (ID INT, NAME VARCHAR(30)) 
DECLARE @TB2 AS TABLE (ID INT, ID_TB1 INT, PRICE DECIMAL(18,2)) 

INSERT INTO @TB1 (ID, NAME) VALUES (1, 'PRODUCT X') 
INSERT INTO @TB1 (ID, NAME) VALUES (2, 'PRODUCT Y') 

INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (1, 1, 3.99) 
INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (2, 1, 4.99) 
INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (3, 1, 5.99) 

INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (1, 2, 0.99) 
INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (2, 2, 1.99) 
INSERT INTO @TB2 (ID, ID_TB1, PRICE) VALUES (3, 2, 2.99) 


SELECT A.ID, A.NAME, B.PRICE 
    FROM @TB1 A 
    INNER JOIN @TB2 B ON A.ID = B.ID_TB1 AND B.ID = (SELECT MAX(ID) FROM @TB2 WHERE ID_TB1 = A.ID) 


END