1

それ自体を参照する階層を格納するために使用されるテーブルがあります。親のノード タイプを決定する SQL ステートメントが必要です。以下に、テーブルの構造とサンプルデータを示して、理解しようとしていることを最もよく説明しています。

ノード テーブル

CREATE TABLE IF NOT EXISTS NODES(id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT NOT NULL, parent_id INTEGER REFERENCES NODES(id) ON DELETE CASCADE

注: parent_idROOT ノードを参照するために NULL にすることができます。

サンプルデータ

INSERT INTO NODES(type, parent_id) VALUES('GRP', NULL); -- id: 1, title: Hello, World!
INSERT INTO NODES(type, parent_id) VALUES('TXT', 1);    -- id: 2, title: Print
INSERT INTO NODES(type, parent_id) VALUES('RND', 1);    -- id: 3, title: Random Output
INSERT INTO NODES(type, parent_id) VALUES('TXT', 3);    -- id: 4, title: OUTPUT #1
INSERT INTO NODES(type, parent_id) VALUES('TXT', 3);    -- id: 5, title: OUTPUT #2
INSERT INTO NODES(type, parent_id) VALUES('TXT', 3);    -- id: 6, title: OUTPUT #3

コメントに記載した各ノードのタイトルがありますが、使いやすさのためにコメントに入れただけです。私が探しているのは、すべてを返す単一の SQL ステートメントを持つことですが、親の属性を使用する OUTPUT #* です。

私の試み

SELECT id
FROM NODES
WHERE parent_id NOT IN (SELECT id
                        FROM NODES
                        WHERE type = 'RND');

私の試みはほとんどの場合うまくいきますが、parent_id は NULL になる可能性があるため、これを調査することJOINで、 a の方がはるかに優れた解決策であることがわかりました。SELF JOIN を希望どおりに機能させる方法がわかりません。

4

2 に答える 2

1

このクエリは、parent_id に基づいてテーブルを結合し、ノードとその親ノードのすべてのフィールドを表示します。左結合が使用されるため、結果にはルート ノードを含むすべてのノードとその親が含まれます。

同じクエリで同じテーブルが 2 回参照されるため、エイリアスを使用して 2 つのテーブルを区別する必要があります。「親としてのノード」という構文は、別名「親」を作成します。

SELECT nodes.*, parent.*
FROM nodes
LEFT JOIN nodes AS parent
ON nodes.parent_id = parent.id

上記のクエリのように、親の型が "RND" と等しくないノードを見つけるには、以下の where 句をクエリに追加する必要があります。

WHERE parent.type != 'RND' OR parent.type IS NULL

上記のクエリに欠けていると思われる重要な点は、NULL 値と比較演算子が連携する方法です。ほとんどの比較演算子とその他の値を使用した NULL の結果は、常に false になります。これが、上記の where 句で 2 番目の条件が必要な理由です。「IS」キーワードは、null 値のチェックに使用できる特別なキーワードです。

于 2013-09-03T20:26:20.003 に答える