web-dev-qa-db-ja.com

SQLJOINとUNIONを一緒に使用する

OK、次のような動作が発生する理由について困惑しました。

「トランザクションヘッダー」テーブルと「トランザクション詳細」テーブルがあります。特定の関数の場合、詳細テーブルでは、「備考」データを抽出するために少し正規化する必要があります。各詳細レコードには、TranRemark1、TranRemark2、およびTranRemark3列で指定された最大3つのコメントを含めることができます。

うまくいくと思って次のクエリをまとめましたが、間違った数のレコードが返されます。

SELECT  
b.ClientName,
a.TranID,
a.TranRemark1,
a.TranDateOfService,
a.TranPayment   
FROM
(select TranRemark1, TranID from TranDetail
union all
select TranRemark2, TranID from TranDetail
union all
select TranRemark3, TranID from TranDetail) AS a
LEFT JOIN TranHeader AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;

私が取得する結果セットは、TranDetailのwhere句に一致するレコードの数ではなく、ClientNameに一致するTranHeaderレコードの数に基づいています。たとえば、クライアント「AcmeInc。」の場合ヘッダーテーブルに3つのレコードがあり、上記のクエリをリマークコード "1234"(TranDetailの1つのレコードのみに一致)に使用すると、結果セットに正しいレコードが3回リストされます。

[〜#〜] edit [〜#〜]したがって、上記の例から、次のような結果セットが得られると思います。

ClientName--TranID--TranRemark1--TranDateOfService--TranPayment
Acme Inc    ADC11   1234         8-16-2011          45.11    

私が得るものはこれです:

ClientName--TranID--TranRemark1--TranDateOfService--TranPayment
Acme Inc    ADC11   1234         8-16-2011          45.11    
Acme Inc    ADC11   1234         8-16-2011          45.11  
Acme Inc    ADC11   1234         8-16-2011          45.11  

TranHeaderには、クライアントの複数のレコードが存在する可能性があることに注意してください。

正しく完全結合を試しましたが、すべて同じようになります。

問題はどこにありますか?

助けてくれてありがとう。

8
nth

交換してみてください:

LEFT JOIN TranHeader AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;

と:

LEFT JOIN
  ( SELECT DISTINCT
        TranId, ClientName
    FROM TranHeader
  ) AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;
8
ypercubeᵀᴹ

どうですか

SELECT
  b.ClientName,
  a.TranID,
  a.TranRemark1,
  a.TranDateOfService,
  a.TranPayment
WHERE a.TranRemark1 = @RemarkID JOIN TranHeader b ON b.TranID = a.TranID
UNION ALL
SELECT
  b.ClientName,
  a.TranID
  a.TranRemark2,
  a.TranDateOfService,
  a.TranPayment
WHERE a.TranRemark2 = @RemarkID JOIN TranHeader b ON b.TranID = a.TranID
UNION ALL
SELECT
  b.ClientName,
  a.TranID,
  a.TranRemark3,
  a.TranDateOfService,
  a.TranPayment
WHERE a.TranRemark3 = @RemarkID JOIN TranHeader b ON b.TranID = a.TranID

私は最初に提案しました

SELECT  
b.ClientName,
a.TranID,
a.TranRemark1,
a.TranDateOfService,
a.TranPayment,
a.TranRemark1,
a.TranRemark2,
a.TranRemark3   
FROM
TranDetail a JOIN TranHeader As b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode 
  OR a.TranRemark2 = @RemarkCode 
  OR a.TranRemark3 = @RemarkCode;

しかし、おそらく発言ごとに別々の行が必要だと思いましたか?

4
Nathan Hughes

UNION ALLを実行する場合は、OUTERSQLでSELECTDISTINCTを実行します。 UNIONを実行すると、重複が処理されます。

UNION ALL with DISTINCTは、私は信じていますが、より良いパフォーマンスを提供します。

0
user2063206

データのフェッチ中にdistinctを使用する

SELECT  distinct
b.ClientName,
a.TranID,
a.TranRemark1,
a.TranDateOfService,
a.TranPayment   
FROM`enter code here`
(select TranRemark1, TranID from TranDetail
union all
select TranRemark2, TranID from TranDetail
union all
select TranRemark3, TranID from TranDetail) AS a
LEFT JOIN TranHeader AS b ON
b.TranID = a.TranID
WHERE a.TranRemark1 = @RemarkCode;
0
Peeyush Jain