2011-08-10 10 views
4
SELECT MD.*, Contact.FirstName 
FROM MerchantData MD 
JOIN Merchant M ON M.MerchID = MD.MerchID 
JOIN (SELECT TOP 1 * FROM Location WHERE Location.BusID = MD.BusID) L ON L.BusID=MD.BusID 
AND L.Deleted = 0 
JOIN Contact ON Contact.ContactID = L.PrincipalID 

私はSQLSERVER 2008を使用してこのSQL文を作成しようとしています。あるbusidのために複数回の場所があり、最初に見つかったものだけに参加したい。 MD.BusIDをバインドできないため、「Location.BusID = MD.BusID」の部分にエラーが表示されます。この結合のネストされた選択文でMDテーブルを使用することは可能ですか、これを達成する別の方法がありますか?T-SQLのトップレコードに参加する

私は列リストにネストされたクエリーを使用してデータを入れて、そこで接触データを取得します。それは単純になり

答えて

8

は、私は完全な結果セットのサブクエリ持っていると思う:

SELECT MD.*, Contact.FirstName 
FROM MerchantData MD 
JOIN Merchant M ON M.MerchID = MD.MerchID 
JOIN (SELECT BusID, MAX(PrincipalID) 
     FROM Location 
     WHERE Deleted = 0 
     GROUP BY BusID) L ON L.BusID=MD.BusID 
JOIN Contact ON Contact.ContactID = L.PrincipalID 

あなたはまだJOINBusIDごとに1つのレコードを取得しますが、それは相関していないです。

+0

問題MAXとは最初と同じではありません – Paparazzi

+1

彼は1つだけ「BusID」を望んでおり、並べ替え順序を指定していません。彼が選んだ場合、ソート基準を追加するのは簡単です。 – JNK

+0

@JNKの問題は、サブセレクションの後にL.Deleted = 0のためこのケースでは機能しません。 –

2

これは、「グループごとの上位n」の問題です。この質問はご案内します。

SQL Server query select 1 from each sub-group

あなたはこのような何かをやっているしたいと思う:

SELECT MD.* , 
     Contact.FirstName 
FROM MerchantData MD 
JOIN Merchant  M ON M.MerchID = MD.MerchID 
JOIN (select * , 
       seq = rank() over(partition by BusID order by BusID , ...) 
     from Location 
     where L.Deleted = 0 
    ) L on L.BusID = MD.BusID 
     and seq  = 1 
JOIN Contact ON Contact.ContactID = L.PrincipalID 

BusIDの場合、仮想テーブル式がBusIDの(0あたり最大1つの場所を返す必要があります削除されていない場所はありません)。

+0

上記の要件は、最初のものを見て、それが最初に削除されたものと同じではないかどうかを確認することです。しかし、あなたのソリューションはエレガントで、あなたは何をしているのかを明確に述べます。 – Paparazzi

4
SELECT MD.*, Contact.FirstName 
FROM MerchantData MD 
JOIN Merchant M ON M.MerchID = MD.MerchID  
CROSS APPLY (SELECT TOP 1 * FROM Location WHERE BusID = MD.BusID AND DELETED = 0) L 
JOIN Contact ON Contact.ContactID = L.PrincipalID 
+0

+1 - 「CROSS APPLY」をうまく使用 – JNK

0

私が試してみるとエラーが発生します。 Location.BusID = MD.BusIDと一致するかどうか確認してください。

SELECT MD.*, Contact.FirstName 
    FROM MerchantData MD 
    JOIN Merchant M ON M.MerchID = MD.MerchID 
    JOIN Location On Location.BusID = MD.BusID 

あなたは構文の作業を取得したら*そう

SELECT TOP 1 Location.BusID FROM Location WHERE Location.BusID = MD.BusID 

を使用して使用しないでください。

この作業を行うと、「最初の」行が一致していて、それが削除されているかどうかを確認します。問題は、「最初の」行による順序なしでは任意であることです。表のクラスタード・インデックスでもorder by節のない保証されたソートはありません。反復可能な答えを得るには、ソートが必要です。しかし、あなたがソートしていて、一番上の行だけが必要な場合は、MAXまたはMINとグループがより単純です。

削除された場所が1つ以上あるビジネスだけの場合は、次の操作は有効ですが、グループの列を分割する必要があります。 2つの削除された場所に異なる連絡先名がある場合は、それぞれを報告します。だから、これはあなたが探しているものではないかもしれません。

SELECT MD.col1, MD.col2, Contact.FirstName 
    FROM MerchantData MD 
    JOIN Merchant M ON M.MerchID = MD.MerchID 
    JOIN Location L 
     ON L.BusID = MD.BusID 
     AND L.Deleted = 0 
    JOIN Contact ON Contact.ContactID = L.PrincipalID 
    GROUP BY MD.col1, MD.col2, Contact.FirstName