2

2つのテーブルがTABLE_AありTABLE_B、結合された列を従業員番号として持っていますEMPNO

通常の左アウター結合をしたい。ただし、TABLE_Bソフト削除された特定のレコード(status='D')があるので、これらを含めたいと思います。明確にするために、TABLE_Bアクティブなレコード(status = null / a / anything)と削除されたレコードがある可能性があります。この場合、結果にその従業員を含めたくありません。ただし、削除された従業員のレコードのみTABLE_Bが含まれている場合は、その従業員を結果に含めたいと思います。要件を明確にしたいと思います。(私は長いqrsltのようなことをして、欲しいものを手に入れることができましたが、結合構文を使用してこれを行うためのより最適化された方法が必要だと思います)。(参加しなくても)提案をいただければ幸いです。彼の新しさは、望ましい結果なしに次のクエリを試行しています。

SELECT TABLE_A.EMPNO
FROM   TABLE_A
LEFT OUTER JOIN TABLE_B ON TABLE_A.EMPNO = TABLE_B.EMPNO AND TABLE_B.STATUS<>'D' 

どんな助けにも感謝します。

4

5 に答える 5

3

明確にするために、テーブルBに「D」以外の彫像のある行がない限り、TABLE_Aのすべてのレコードが表示されますか?

Bには少なくとも1つのnull以外の列が必要です(例として「B.ID」を使用します。このアプローチは機能するはずです)。

SELECT TABLE_A.EMPNO
FROM TABLE_A
LEFT OUTER JOIN TABLE_B ON
  (TABLE_A.EMPNO = TABLE_B.EMPNO)
  AND (TABLE_B.STATUS <> 'D' OR TABLE_B.STATUS IS NULL)
WHERE
  TABLE_B.ID IS NULL

つまり、考えられるロジックを逆にします。TABLE_Aエントリを除外する行がある場合にのみTABLE_Bに結合し、最後にISNULLを使用してそれらを除外します。これは、一致しなかったもの(TABLE_Bに行がないもの、または「D」行のみがあるもの)のみが含まれることを意味します。

代替案は

SELECT TABLE_A.EMPNO
FROM TABLE_A
WHERE NOT EXISTS (
  SELECT * FROM TABLE_B 
  WHERE TABLE_B.EMPNO = TABLE_A.EMPNO
  AND (TABLE_B.STATUS <> 'D' OR TABLE_B.STATUS IS NULL)
)
于 2009-08-24T12:22:58.860 に答える
0

ああ、これは明らかに機能します> <

SELECT TABLE_A.EMPNO
FROM   TABLE_A
LEFT OUTER JOIN TABLE_B ON TABLE_A.EMPNO = TABLE_B.EMPNO 
where TABLE_B.STATUS<>'D'

チャイムをするための追加情報があれば、お気軽にどうぞ。

更新: しばらくしてからこの質問を見て、もっと役立つ情報を追加すると思いました:このリンクにはANSI構文に関する優れた情報があります-http: //www.oracle-base.com/articles/9i/ANSIISOSQLSupport.php

特に、リンクされたページのこの部分は有益です。

ANDを使用して複雑な結合を形成するために、結合に追加のフィルター条件を追加できます。これらは、外部結合を制限するためにフィルター条件が必要な場合に必要になることがよくあります。これらのフィルター条件がWHERE句に配置され、外部結合がフィルター列にNULL値を返す場合、行は破棄されます。フィルタ条件が結合の一部としてコーディングされている場合、この状況を回避できます。

于 2009-08-24T12:16:42.087 に答える
0

次のクエリは、削除されていない従業員レコード、または従業員のみが削除されたレコードのみを取得します。

select
    a.*
from
    table_a a
    left join table_b b on
        a.empno = b.empno
where
    b.status <> 'D'
    or (b.status = 'D' and 
        (select count(distinct status) from table_b where empno = a.empno) = 1)

これはANSISQLに含まれていますが、RDBMSを知っていれば、もう少し洗練された、より具体的なソリューションを提供できます。

于 2009-08-24T12:21:37.457 に答える
0

これが私が質問を理解する方法です。次のいずれかに該当する従業員のみを含める必要があります。

  • 従業員は、(ソフト) 削除された行のみを持っていTABLE_Bます。

  • 従業員には、削除されていない行しかありませんTABLE_B

  • 従業員には行がまったくありませんTABLE_B

つまり、従業員が に削除された行と削除されていない行の両方を持っているTABLE_B場合はその従業員を省略し、そうでない場合は含めます。

これは私がそれを解決できると思う方法です:

SELECT DISTINCT a.EMPNO
FROM TABLE_A a
  LEFT JOIN TABLE_B b1 ON a.EMPNO = b1.EMPNO
  LEFT JOIN TABLE_B b2 ON b1.EMPNO = b2.EMPNO
    AND (b1.STATUS = 'D' AND (b2.STATUS <> 'D' OR b2 IS NULL) OR
         b2.STATUS = 'D' AND (b1.STATUS <> 'D' OR b1 IS NULL))
WHERE b2.EMPNO /* or whatever non-nullable column there is */ IS NULL

または、グループ化を使用することもできます。

SELECT a.EMPNO
FROM TABLE_A a
  LEFT JOIN TABLE_B b ON a.EMPNO = b1.EMPNO
GROUP BY a.EMPNO
HAVING 0 IN (COUNT(CASE b.STATUS WHEN 'D' THEN 1 ELSE NULL END),
             COUNT(CASE b.STATUS WHEN 'D' THEN NULL ELSE 1 END))
于 2011-06-10T08:34:11.427 に答える
0
SELECT A.*, B.*
FROM
   Table_A A
   INNER JOIN Table_B B
      ON A.EmpNo = B.EmpNo
WHERE
   NOT EXISTS (
      SELECT *
      FROM Table_B X
      WHERE
          A.EmpNo = X.EmpNo
          AND X.Status <> 'D'
    )

これでうまくいくと思います。すべての (少なくとも 1 つの) 行が削除された従業員のみを含める必要があるため、左結合は必要ありません。

于 2011-06-10T07:23:57.333 に答える