2010-12-16 2 views
16

私は2つのテーブルを持っています。テーブル「B」はテーブル「A」と1対多の関係にあり、テーブル「A」の1レコードに対してテーブル「B」に多くのレコードが存在することを意味します。t-sqlの「最新の」レコードにのみ結合する

テーブル "B"のレコードは主に日付で区別されるため、テーブル "B"の最新のレコードのみで結合されたレコードを含む結果セットを生成する必要があります。説明の目的のために、ここではサンプル・スキーマです:

Table A 
------- 
ID 

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

私は私がいただければ幸いです任意の助けを探していResultSetを与えるために、クエリを策定するトラブルを抱えています。

+0

を記録? DateTime2は3ms(またはそのようなもの)にしか良いとは言いませんが、DateTime2はナノ秒まで測定できます(より正確です)。 –

+0

[Table A]と[Table B]を結合する列はTableAIDですか? – Lamak

+0

これを含める必要があります...あなたは、日付時刻が重複しないと仮定することができますので、常に最新の:-) –

答えて

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

+1

これは完全に質問に完全には答えませんそれはテーブルbから最大の行の日付だけを取得するためです。質問は最新の行を要求しています - したがって、テーブルBの残りの部分をその行に戻す必要があります。また、TableA参照の同じ日付/時刻の2つのエントリを持つテーブルBを考慮する必要があります。 –

+0

@Paul: TableBは、OPによって指定されたフィールドのみを持っています。あなたが言及したケースを処理するように変更されたクエリを持っている。重複はユーザーのデータの問題である場合もありません。 – RedFilter

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

外側の適用ははるかに迅速です! –

+1

私のシステムで試した他のアプローチと比較して、その外側への適用は急速です。 –

+0

私は受け入れられた答えとこの答えをテストしたところ、外側の適用は受け入れられた答えより約2倍遅かったことがわかりました! – Maderas

0

ちょうど明快さのために、そしてうんざりする人に利益をもたらすためにこの古代の質問。受け入れられた答えは、に重複した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

この使用してみてください:あなたが最新シングルを定義する方法、テーブルBと同じ日時を持つ2つの列の場合は

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 
関連する問題