web-dev-qa-db-ja.com

他の3つの列の組み合わせの重複する値に基づいて、列の値が異なる行を取得します

他の3つの列の一意の組み合わせを持つ重複行に基づいて、列(列名DEF)に異なる値を持つ行のみを取得したい。

例:以下の例では、最初の2つの行の最初の3列は同じ値ですが、列DEFの値は異なります。したがって、これらの両方の行が出力にリストされます。

ただし、行2と4には最初の3列の一意の組み合わせがありますが、DEF列には同じ値があるため、出力には表示されません。

行5と6は、値が異なる単一行であるため、リストされません。

+----------+-------+--------+--------+
| dept     | role1 |role2   |DEF     |
+----------+-------+--------+--------+
| a        | abc   | er     | 0      |
| a        | abc   | er     | 1      |
| b        | qwer  | ty     | 0      |
| b        | qwer  | ty     | 0      |
| c        | der   | ui     | 1      |
| d        | nerr  | io     | 0      |
+----------+-------+--------+--------+
output

+----------+------+------+------+
| dept     | role1|role2 |DEF   |
+----------+------+------+------+
| a        | abc  | er   |0     |
| a        | abc  | er   |1     |
+----------+------+------+------+

列DEFの値を確認することはできますが、目的の結果を得ることはできません。

誰かが私を助けてくれますか?

9
Navaneet

ほとんどのRDBMSで標準SQLを使用するには、さまざまな方法があります。

サブクエリを使用する:

SELECT d.dept, d.role1, d.role2, DEF
FROM data d
INNER JOIN (
    SELECT dept, role1, role2 
    FROM data
    GROUP BY dept, role1, role2
    HAVING COUNT(distinct DEF) > 1
) dup
    ON dup.dept = d.dept AND dup.role1 = d.role1 AND dup.role2 = d.role2
;

サブクエリは、複数の異なるDEFを含むdept/role1/role2のセットを返します。

相関サブクエリを使用する:

SELECT d.dept, d.role1, d.role2, DEF
FROM @data d
WHERE EXISTS (
    SELECT 1 
    FROM @data 
    WHERE dept = d.dept AND role1 = d.role1 AND role2 = d.role2 AND DEF <> d.DEF
);

サブクエリは0〜n行を返します。少なくとも1つの行が存在する場合、メインテーブルの行が返されます。

CROSS APPLYの使用:

SELECT d.dept, d.role1, d.role2, d.DEF
FROM @data d
CROSS APPLY (
    SELECT n=1 
    FROM @data 
    WHERE dept = d.dept AND role1 = d.role1 AND role2 = d.role2 AND DEF <> d.DEF
) ca
;

CROSS APPLYは、OracleまたはSQL Serverで動作します。

出力:

dept    role1   role2   DEF
a       abc     er      0
a       abc     er      1
13