0

私の質問は、私の思考の問題は何ですか?

左結合が思ったように機能しないのはなぜですか?

ここで、有効な答えが(説明なしで)与えられました。

詳細情報は下にあります。

左外部結合を使用するときに直面している問題を表示するこのSQLフィドルがあります

構造

CREATE TABLE IF NOT EXISTS `mychanges` (
  `object_id` int(11) unsigned NOT NULL,
  `version_stamp` datetime DEFAULT NULL,
  `object_name` varchar(255) DEFAULT NULL,
  `project` int(11) unsigned DEFAULT NULL,
  PRIMARY KEY (`object_id` ,`version_stamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

    INSERT INTO mychanges VALUES (1266, "2014-09-24 09:55:40", "bbbb", 2 );
    INSERT INTO mychanges VALUES (1236, "2014-09-24 09:55:40", "aaa", 2 );
    INSERT INTO mychanges VALUES (1226, "2014-09-24 09:55:40", "zzz", 5 );
    INSERT INTO mychanges VALUES (1216, "2014-09-24 09:55:40", "xxxx", 8 );

    INSERT INTO mychanges VALUES (1256, "2014-09-24 09:51:40", "name1", 10 );
    INSERT INTO mychanges VALUES (1256, "2014-09-24 09:52:40", "name2", 10 );
    INSERT INTO mychanges VALUES (1256, "2014-09-24 09:53:40", "name3", 10 );
    INSERT INTO mychanges VALUES (1256, "2014-09-24 09:54:40", "name4", null );
    INSERT INTO mychanges VALUES (1256, "2014-09-24 09:56:40", "name5", null );

選択する

SELECT  mychanges.object_id AS objectid1, mychanges.object_name AS objectname1, mychanges.version_stamp AS version_stamp1, change2.project as project2, change2.version_stamp as version_stamp2, change2.object_name as objectname2 FROM mychanges
LEFT JOIN (SELECT * from mychanges AS x WHERE x.project IS NULL) AS change2
ON change2.object_id = mychanges.object_id 
WHERE  mychanges.project = 10

私が取得したいもの:

によって挿入される値

INSERT INTO mychanges VALUES (1256, "2014-09-24 09:51:40", "name1", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:52:40", "name2", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:53:40", "name3", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:54:40", "name4", null );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:56:40", "name5", null );

つまり、書き言葉では、プロジェクトとして 10 を持つすべてのレコードと、プロジェクト ID が 10 のレコードと同じオブジェクト ID を持つすべてのレコードです。

なんで?

これはチェンジセット テーブルです。ユーザーがオブジェクト名を変更しているときに Enter キーを押します。これにより、変更の形式でエントリが生成されます。これらの変更は、悲しいことに、プロジェクト ID が null になる可能性があります。ただし、オブジェクト ID は一意です。

私は何を考えていますか?

私は考えました: project_id NULL を持つすべてのエントリがあります。左側には、project_id が 10 のすべてのレコードがありますobject_id。しかし代わりに、name1、name2、および name3 ではなく、name4 と name5 の複製を取得します。

なぜだめですか?

4

1 に答える 1

1

私は考えました: project_id NULL を持つすべてのエントリがあります。左側には、project_id が 10 のすべてのレコードがあります。それらを結合すると、重複なしで両方が得られます。

いいえNULL値は他の値と比較できないため、結合できませんNULL。null がある場合は、ifNULL()関数を使用して明示的に処理する必要があります。

編集

もう一度見てみるとobject_id、もちろん null ではない に参加しようとしていることがわかります。それでは、クエリで何が起こっているのか見てみましょう。クエリを 2 つの部分に分割する場合、最初の部分は次のとおりです。

SELECT  
mychanges.object_id AS objectid1, 
mychanges.object_name AS objectname1, 
mychanges.version_stamp AS version_stamp1
FROM mychanges
WHERE  mychanges.project = 10

object_idこれにより、 = 1256の 3 つのレコードが生成されます

そして第2弾は、

SELECT * from mychanges AS x WHERE x.project IS NULL

object_idこれにより、 = 1256の 2 つのレコードが生成されます。

条件を使用してこれら 2 つの部分を結合するchange2.object_id = mychanges.object_idと、結果として 3 X 2 = 6 レコードが生成されます。重複は左側のレコードごとに発生し、右側に 2 つのレコードがあります。

これは、まさに SQL の動作が想定されていることです。

于 2014-11-26T09:48:56.717 に答える