2011-09-13 10 views
4

私はCOALESCEについて学びましたが、2つのテーブル間でデータ行全体をCOALESCEできるかどうか疑問に思っていますか?そうでない場合、次の話題への最良のアプローチは何ですか?Sql全体の行がCOALESCEですか?

たとえば、私はこれらの2つのテーブルを持っており、すべての列が一致すると仮定:

tbl_Employees

Id  Name  Email  Etc 
----------------------------------- 
1  Sue  ...  ... 
2  Rick  ...  ... 

tbl_Customers

Id  Name  Email  Etc 
----------------------------------- 
1  Bob  ...  ... 
2  Dan  ...  ... 
3  Mary  ...  ... 

とIDの持つテーブル:

tbl_PeopleInCompany

Id  CompanyId 
----------------- 
1  1 
2  1 
3  1 

そして私は、一致のidの持つ最初のテーブルから行を取得しますが、何のidが見つからない場合は、2番目のテーブルから取得する方法でデータを照会します。

だから、結果のクエリは次のようになります。

スーとリックは、第二から最初のテーブルから取った、とメアリーた
Id  Name  Email  Etc 
----------------------------------- 
1  Sue  ...  ... 
2  Rick  ...  ... 
3  Mary  ...  ... 

+2

'tbl_PeopleInId'テーブルの目的は何ですか? 'tbl_Employees'から' tbl_Customers'まで 'FULL OUTER JOIN'だけで、あなたが望む結果を得ることができるようです。また、あなたは実用的な目的を求めていないと思います。 –

+0

ちょっとマーティン、私はtbl_PeopleInIsが例のためにあまりにも希釈されていると思います。もっと理にかなって編集しました。基本的には、2つのデータセット間の関係のためのテーブル。 – Levitikon

答えて

7
SELECT Id, Name, Email, Etc FROM tbl_Employees 
     WHERE Id IN (SELECT ID From tbl_PeopleInID) 
UNION ALL 
SELECT Id, Name, Email, Etc FROM tbl_Customers 
     WHERE Id IN (SELECT ID From tbl_PeopleInID) AND 
      Id NOT IN (SELECT Id FROM tbl_Employees) 

これらのクエリを(JOINとEXISTSを使用して)記述する方法はいくつかありますが、最初に試してみてください。

このクエリでは、最初にターゲットリスト(テーブルtbl_PeopleInID)のId値を持つすべての人をtbl_Employeesから選択します。次には、この一連の行の「ボトム」に第2のクエリの結果をと追加します。 2番目のクエリは、ターゲットリストにあるIDがtbl_Employeesに表示されているすべてのtbl_Customer行を取得しますが、は、を除きます。

合計リストには、tbl_PeopleInIDのすべてのIDが優先され、従業員には与えられていますが、顧客からプルされたレコードはありません。

+0

これはうまくいくと思います。 Lemmeはそれにショットを与えます – Levitikon

+0

+1最初は空ではなく、 'COALESCE()'は必要ありません!この解答の説明は「ダムダウン」されていますが、コードは健全な関係演算子を使用しています。つまり、結合、半結合( 'IN')と準差異(' NOT IN')です。 – onedaywhen

0

私はCOALESCE機能をあなたが思っているものに使うことはできないと思います。それはあなたが複数で列を渡すことができますし、最初の非null値を返します以外COALESCEは、ISNULLのようになります。

http://msdn.microsoft.com/en-us/library/ms190349.aspx

SELECT Name, Class, Color, ProductNumber, 
COALESCE(Class, Color, ProductNumber) AS FirstNotNull 
FROM Production.Product 

この記事には、アプリケーションの説明する必要があります

Larry Lustigの答えは、あなたが必要とするもののラインに沿っているように聞こえます。

3

また、これを行うことができます。

1)外はtbl_Employees.Id = tbl_Customers.Id上の2つのテーブルを結合します。これにより、tbl_Employeesからすべての行が取得され、一致する行がない場合は、tbl_Customers列がnullのままになります。

2)ユースケースtbl_Employees列またはtbl_Customers列のいずれかを選択するには、tbl_Customers.IdがNULLであるかどうかに基づいて、このような:

CASE WHEN tbl_Customers.Id IS NULL THEN tbl_Employees.Name ELSE tbl_Customers.Name END AS Name 

(私の構文は、そこに完璧ではないかもしれませんが、技術音である)。

+0

私は、2つのテーブルが多くのカラムを持ち、時間の経過と共に成長する可能性があるので、個々のカラムを合体させないようにしようとしています。 – Levitikon

+1

@JohnC 'case'の代わりに、' tbl_Employees.Name'がnullでなければ、同じセマンティクスを持つ 'coalesce(tbl_Employees.Name、tbl_Customers.Name)Name'を使うことができます。 – Josh

+0

@ Levitikon: "SELECT *"と "UNION ALL"を一緒に実行するのは脆弱です。 2つのテーブルが全く同じになる必要があります。いずれかの表に列が追加されると、その列は分解されます。このような変更にもかかわらず、より弾力性を持たせるためには、列名を指定することをお勧めします。 – JohnC

0

これはかなり効果があります。それは基本的に一致する従業員レコードを持っていないお客様の小さなテーブルを構築するためにCTEを使用し、それIN演算子を使用して従業員レコード

;WITH FilteredCustomers (Id, Name, Email, Etc) 
AS 
(
    SELECT Id, Name, Email, Etc 
    FROM tbl_Customers C 
      INNER JOIN tbl_PeopleInCompany PIC 
      ON C.Id = PIC.Id 
      LEFT JOIN tbl_Employees E 
      ON C.Id = E.Id 
    WHERE E.Id IS NULL 
) 

SELECT Id, Name, Email, Etc 
FROM tbl_Employees E 
     INNER JOIN tbl_PeopleInCompany PIC 
     ON C.Id = PIC.Id 

UNION 

SELECT Id, Name, Email, Etc 
FROM FilteredCustomers 

となり、単にUNION sがかなりのような大きなクエリに課税することができ処理される各レコードの副照会を評価する必要があります。

+0

質問にタグが表示されていない場合は、これがSQL Serverであることを示しているため、ユーザーはCTEを利用できない可能性があります。また、サブクエリは相関関係がないかぎり、行ごとの評価を必要としません。 –

+0

非常に公正で、上のCTEの代わりに一時テーブルを使うこともできます: – ericb

関連する問題