2番目の改訂された回答
コメントには、T2に重複する行が存在する可能性があると記載されているため、さらに複雑なソリューションが必要です。これが正しいデータを生成すると私が信じるクエリです。
-- Query 8B
SELECT x.id
FROM (SELECT d2.id, d2.c, d2.d
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS d2
JOIN (SELECT id
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS x
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id)
) AS j2
ON j2.id = d2.id
) AS x
JOIN (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS y
ON x.c = y.c AND x.d = y.d
GROUP BY x.id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id);
それが可能な限り単純であるかどうかは疑問ですが、それは以前に改訂された回答の論理的な続きです。
実行例
これは、開発された手順を示すクエリのトレース出力です。DBMSは、Mac OSX10.7.4で実行されるIBMInformixDynamic Server 11.70.FC2であり、SQLコマンドインタープリターとしてSQLCMD v88.00を使用します(いいえ、Microsoftのjohnny-come-latelyではありません。20年以上前に最初に作成したものです)。 。
+ BEGIN;
+ CREATE TABLE T1
(ID INTEGER NOT NULL PRIMARY KEY, a CHAR(1) NOT NULL, b CHAR(1) NOT NULL);
+ INSERT INTO T1 VALUES(1, 'k', 'l');
+ INSERT INTO T1 VALUES(2, 'k', 'l');
+ INSERT INTO T1 VALUES(3, 'a', 'b');
+ INSERT INTO T1 VALUES(4, 'p', 'q');
+ INSERT INTO T1 VALUES(5, 't', 'v');
+ CREATE TABLE T2
(IDFK INTEGER NOT NULL REFERENCES T1, c CHAR(1) NOT NULL, d CHAR(1) NOT NULL);
+ INSERT INTO T2 VALUES(1, 'w', 'x');
+ INSERT INTO T2 VALUES(1, 'y', 'z');
+ INSERT INTO T2 VALUES(2, 'w', 'x');
+ INSERT INTO T2 VALUES(2, 'w', 'x');
+ INSERT INTO T2 VALUES(2, 'y', 'z');
+ INSERT INTO T2 VALUES(3, 'w', 'x');
+ INSERT INTO T2 VALUES(3, 'y', 'b');
+ INSERT INTO T2 VALUES(3, 'y', 'z');
+ INSERT INTO T2 VALUES(4, 'w', 'x');
+ INSERT INTO T2 VALUES(5, 'w', 'x');
+ INSERT INTO T2 VALUES(5, 'y', 'z');
+ INSERT INTO T2 VALUES(5, 'w', 'x');
+ INSERT INTO T2 VALUES(5, 'y', 'z');
+ SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1;
2|w|x
2|y|z
3|w|x
3|y|b
3|y|z
4|w|x
5|w|x
5|y|z
+ SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1;
1|w|x
1|y|z
+ SELECT id, COUNT(*) FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS x GROUP BY id;
2|2
5|2
3|3
4|1
+ SELECT id, COUNT(*) FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x GROUP BY id;
1|2
+ -- Query 5B - IDs having same count of distinct rows as ID = 1
SELECT id
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS x
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id);
2
5
+ -- Query 6B
SELECT d2.id, d2.c, d2.d
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS d2
JOIN (SELECT id
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS x
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id)
) AS j2
ON j2.id = d2.id
ORDER BY id;
2|w|x
2|y|z
5|w|x
5|y|z
+ -- Query 7B
SELECT x.id, y.id, x.c, y.c, x.d, y.d
FROM (SELECT d2.id, d2.c, d2.d
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS d2
JOIN (SELECT id
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS x
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id)
) AS j2
ON j2.id = d2.id
) AS x
JOIN (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS y
ON x.c = y.c AND x.d = y.d
ORDER BY x.id, y.id, x.c, x.d;
2|1|w|w|x|x
2|1|y|y|z|z
5|1|w|w|x|x
5|1|y|y|z|z
+ -- Query 8B
SELECT x.id
FROM (SELECT d2.id, d2.c, d2.d
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS d2
JOIN (SELECT id
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk != 1) AS x
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id)
) AS j2
ON j2.id = d2.id
) AS x
JOIN (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS y
ON x.c = y.c AND x.d = y.d
GROUP BY x.id
HAVING COUNT(*) = (SELECT COUNT(*)
FROM (SELECT DISTINCT idfk AS id, c, d FROM t2 WHERE idfk = 1) AS x
GROUP BY id);
2
5
+ ROLLBACK;
最初に改訂された回答
ステップ1:ID=1と同じ行数のID
SELECT idfk AS id -- Query 5
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1);
ステップ2:クエリ5に対応するデータ
SELECT idfk AS id, c, d -- Query 6
FROM t2
JOIN (SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1)
) AS j2
ON j2.id = t2.idfk
ORDER BY id;
ステップ3:クエリ6の行をID=1の行と結合します
SELECT x.id, y.id, x.c, y.c, x.d, y.d -- Query 7
FROM (SELECT idfk AS id, c, d
FROM t2
JOIN (SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1)
) AS j2
ON j2.id = t2.idfk
) AS x
JOIN (SELECT idfk AS id, c, d
FROM t2 WHERE idfk = 1
) AS y
ON x.c = y.c AND x.d = y.d
ORDER BY x.id, y.id, x.c, x.d;
ステップ4:カウントがID=1のカウントと同じであるクエリ7からのID
SELECT x.id
FROM (SELECT idfk AS id, c, d
FROM t2
JOIN (SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1)
) AS j2
ON j2.id = t2.idfk
) AS x
JOIN (SELECT idfk AS id, c, d
FROM t2 WHERE idfk = 1
) AS y
ON x.c = y.c AND x.d = y.d
GROUP BY x.id
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1);
実行例
DBMSは、Mac OSX10.7.4で実行されるIBMInformixDynamic Server 11.70.FC2であり、SQLコマンドインタープリターとしてSQLCMD v88.00を使用します(いいえ、Microsoftのjohnny-come-latelyではありません。20年以上前に最初に作成したものです)。 。
+ BEGIN;
+ CREATE TABLE T1
(ID INTEGER NOT NULL PRIMARY KEY, a CHAR(1) NOT NULL, b CHAR(1) NOT NULL);
+ INSERT INTO T1 VALUES(1, 'k', 'l');
+ INSERT INTO T1 VALUES(2, 'k', 'l');
+ INSERT INTO T1 VALUES(3, 'a', 'b');
+ INSERT INTO T1 VALUES(4, 'p', 'q');
+ CREATE TABLE T2
(IDFK INTEGER NOT NULL REFERENCES T1, c CHAR(1) NOT NULL, d CHAR(1) NOT NULL);
+ INSERT INTO T2 VALUES(1, 'w', 'x');
+ INSERT INTO T2 VALUES(1, 'y', 'z');
+ INSERT INTO T2 VALUES(2, 'w', 'x');
+ INSERT INTO T2 VALUES(2, 'y', 'z');
+ INSERT INTO T2 VALUES(3, 'w', 'x');
+ INSERT INTO T2 VALUES(3, 'y', 'b');
+ INSERT INTO T2 VALUES(3, 'y', 'z');
+ INSERT INTO T2 VALUES(4, 'w', 'x');
+ SELECT t1.id AS id, t2.c, t2.d -- Query 1
FROM t1
JOIN t2 ON t1.id = t2.idfk;
1|w|x
1|y|z
2|w|x
2|y|z
3|w|x
3|y|b
3|y|z
4|w|x
+ -- Query 5 - IDs having same count of rows as ID = 1
SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1);
2
+ SELECT idfk AS id, c, d
FROM t2
JOIN (SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1)
) AS j2
ON j2.id = t2.idfk
ORDER BY id;
2|w|x
2|y|z
+ SELECT x.id, y.id, x.c, y.c, x.d, y.d
FROM (SELECT idfk AS id, c, d
FROM t2
JOIN (SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1)
) AS j2
ON j2.id = t2.idfk
) AS x
JOIN (SELECT idfk AS id, c, d
FROM t2 WHERE idfk = 1
) AS y
ON x.c = y.c AND x.d = y.d
ORDER BY x.id, y.id, x.c, x.d;
2|1|w|w|x|x
2|1|y|y|z|z
+ SELECT x.id
FROM (SELECT idfk AS id, c, d
FROM t2
JOIN (SELECT idfk AS id
FROM t2
WHERE idfk != 1
GROUP BY idfk
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1)
) AS j2
ON j2.id = t2.idfk
) AS x
JOIN (SELECT idfk AS id, c, d
FROM t2 WHERE idfk = 1
) AS y
ON x.c = y.c AND x.d = y.d
GROUP BY x.id
HAVING COUNT(*) = (SELECT COUNT(*) FROM t2 WHERE t2.idfk = 1);
2
+ ROLLBACK;
元の回答
これにより、少なくとも質問が十分に明確になりました。
私が知る限り、次のようなサブクエリがある場合:
SELECT t1.id AS id, t2.c, t2.d -- Query 1
FROM t1
JOIN t2 ON t1.id = t2.idfk
c
次に、との値はd
同じであるがid
値が異なる結果セット内の行のペアを探しています。したがって、それに基づいてメインクエリを記述します。
SELECT j1.id, j2.id -- Query 2
FROM (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j1
JOIN (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j2
ON j1.c = j2.c AND j1.d = j2.d AND j1.id != j2.id
!=
条件をまたはのいずれかに<
変更することで、「1、2」と「2、1」の両方を取得しないようにすることができます>
。
T1の特定のID値に一致する行が必要な場合は、WHERE句で指定できます。
SELECT j2.id -- Query 3
FROM (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j1
JOIN (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j2
ON j1.c = j2.c AND j1.d = j2.d AND j1.id != j2.id
WHERE j1.id = 1; -- 1 is the ID for which matches are sought
必要に応じて、サブクエリに条件を追加できます(ただし、優れたオプティマイザがそれを実行できる場合があります)。
SELECT j2.id -- Query 4
FROM (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk AND t1.id = 1
) AS j1
JOIN (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk AND t1.id != 1
) AS j2
ON j1.c = j2.c AND j1.d = j2.d
WHERE j1.id = 1; -- 1 is the ID for which matches are sought
メインのON句の3番目の条件は冗長でした。これは、構造上、サブクエリのID値j1
がすべて1であり、サブクエリのID値j2
がすべて「1ではない」ためです。
t2.id
SQLのvsの問題を修正し、t2.idfk
上記の4つのクエリを実行しました。それぞれが私が期待する答えを生み出します。たとえば、クエリ4の結果セットには2つの行があります。これは、T1に2組の行があり、T2に行{1、 a、b }と{2、a、b }の両方が存在するためです。一致する行が多数あるにもかかわらず、2つだけを1回だけ表示したい場合は、SELECTにDISTINCTを適用する必要があります。
コメントで、あなたは言います:
残念ながら、属性の1つが一致しなくても、結果が返されます。T2のすべての属性を一致させる方法は?
それを実証するには、拡張データセットが必要です。追加したとき:
INSERT INTO T1 VALUES(3, 'a', 'b');
INSERT INTO T2 VALUES(3, 'a', 'z');
INSERT INTO T2 VALUES(3, 'y', 'b');
値3は、クエリ1の結果にのみ表示されます。これは、表示される唯一の場所です。
サンプルデータを示して、あなたが間違った行動として見ているものを説明してください。上記のクエリを次のSQLとインターリーブされたクエリ結果でテストしました。DBMSは、Mac OSX10.7.4で実行されるIBMInformixDynamic Server 11.70.FC2であり、SQLコマンドインタープリターとしてSQLCMDv88.00を使用します。
+ BEGIN;
+ CREATE TEMP TABLE T1
(ID INTEGER NOT NULL PRIMARY KEY, A CHAR(1) NOT NULL, B CHAR(1) NOT NULL);
+ INSERT INTO T1 VALUES(1, 'k', 'l');
+ INSERT INTO T1 VALUES(2, 'k', 'l');
+ INSERT INTO T1 VALUES(3, 'a', 'b');
+ CREATE TEMP TABLE T2
(IDFK INTEGER NOT NULL, C CHAR(1) NOT NULL, D CHAR(1) NOT NULL);
+ INSERT INTO T2 VALUES(1, 'w', 'x');
+ INSERT INTO T2 VALUES(1, 'y', 'z');
+ INSERT INTO T2 VALUES(2, 'w', 'x');
+ INSERT INTO T2 VALUES(2, 'y', 'z');
+ INSERT INTO T2 VALUES(3, 'a', 'z');
+ INSERT INTO T2 VALUES(3, 'y', 'b');
+ SELECT t1.id AS id, t2.c, t2.d -- Query 1
FROM t1
JOIN t2 ON t1.id = t2.idfk;
1|w|x
1|y|z
2|w|x
2|y|z
3|a|z
3|y|b
+ SELECT j1.id, j2.id -- Query 2
FROM (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j1
JOIN (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j2
ON j1.c = j2.c AND j1.d = j2.d AND j1.id != j2.id;
1|2
1|2
2|1
2|1
+ SELECT j2.id -- Query 3
FROM (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j1
JOIN (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk
) AS j2
ON j1.c = j2.c AND j1.d = j2.d AND j1.id != j2.id
WHERE j1.id = 1;
2
2
+ SELECT j2.id -- Query 4
FROM (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk AND t1.id = 1
) AS j1
JOIN (SELECT t1.id AS id, t2.c, t2.d
FROM t1
JOIN t2 ON t1.id = t2.idfk AND t1.id != 1
) AS j2
ON j1.c = j2.c AND j1.d = j2.d
WHERE j1.id = 1;
2
2
+ ROLLBACK;