重要

翻訳は あなたが参加できる コミュニティの取り組みです。このページは現在 69.28% 翻訳されています。

16.4. Connecting and Editing Data Across Layers

Ability to connect data from different layers is one of the duties of a GIS software. Such a connection can be based on the spatial relationship between the features, or on their shared attributes. QGIS provides tools to handle any of these associations, such as:

  • Processing algorithms that can create a new layer as a result of the connection, namely 属性の空間結合, 属性の最近傍結合, 属性テーブルで結合(table join), ...

  • SQL queries to create a new layer from the DB Manager or as a virtual layer

  • Joins properties or relations settings that temporarily extend attributes of features in a given layer, with those of features in another layer based on some matching attribute(s).

    Joins and relations are technical concepts borrowed from databases to get the most out of data stored in tables by combining their contents. The idea is that features (rows) of different layers (tables) can be associated to each other. The number of rows which are matching each other can be of any value (zero, one, many).

16.4.1. Joining features between two layers

Joins in QGIS allow you to associate features of the current layer to features from another loaded vector layer. Whether they are spatially enabled and the type of geometry do not matter. The join is based on an attribute that is shared by the layers, in a one-to-one relationship.

To create a join on a layer (identified below as target layer):

  1. Go to the layer Properties ► join Joins tab

  2. symbologyAdd 新しい結合を追加 ボタンをクリックします。 ベクタ結合を追加 ダイアログが現れます。

  3. ターゲットベクタレイヤと結合させたい 結合するレイヤ を選択します。

  4. Specify the Join field (from the join layer) and the Target field (from the target layer). These are the fields that are used to find matching feature in both layers hence they should have values in common.

  5. OK ボタンを押すと、選択したパラメータの概要が テーブル結合 パネルに表示されます。

../../../_images/join_attributes.png

図 16.101 既存のベクタレイヤに属性テーブルを結合する

The steps above will create a join, where ALL the attributes of the first matching feature in the join layer is added to the target layer's feature. The following logic is used to pair features during a join process:

  • All the features in the target layer are returned, regardless they have a match

  • If the target field contains duplicate values, these features are assigned the same feature from the join layer.

  • If the join field contains duplicate matching values, only the first fetched feature is picked.

注釈

Joins in QGIS are based on a single field matching so most of the times, you would want to make sure that values in the matchable fields are unique.

QGIS provides some more options to tweak the join:

  • checkbox 結合レイヤをキャッシュ :ルックアップを高速化するために、結合レイヤの値を(ジオメトリなしで)メモリにキャッシュできるようになります。

  • unchecked Create attribute index on the join field to speed up lookups

  • unchecked 動的フォーム(結合レイヤと連動)ターゲットフィールド の変更に応じて結合フィールドをオンザフライで同期できるようになります。これにより、結合フィールドの制約条件も適切に更新されます。多数の地物があったり無数の結合がある場合には非常に時間がかかることがあるため、この機能はデフォルトでは無効化されていることに注意してください。

  • ターゲットレイヤが編集可能な場合には、フィールドの横の属性テーブルにはステータスを知らせるためのアイコンが表示されます:

    • joinNotEditable :結合レイヤが編集可能に設定されていません。ターゲットの属性テーブルから結合地物を編集できるようにしたい場合は、 checkbox 編集可能な結合レイヤ オプションにチェックを入れる必要があります。

    • joinedLayerNotEditable :結合レイヤは編集可能に設定されていますが、現在のステータスは読み取り専用です。

    • joinHasNotUpsertOnEdit: the join layer is editable, but synchronization mechanisms are not activated. If you want to automatically add a feature in the join layer when a feature is created in the target layer, then you have to check the option checkbox Upsert on edit. Symmetrically, the option checkbox Delete cascade may be activated if you want to automatically delete join features.

  • unchecked 結合フィールド :結合するレイヤの全てのフィールドを追加するのではなく、その一部分を指定することができます。

  • unchecked カスタムフィールド名の接頭辞 :名前の衝突を回避するために付けられる結合フィールド名の接頭辞をカスタマイズできます。

16.4.2. Setting relations between multiple layers

Unlike joins that define a one-to-one link between features across two layers, relations help you build interconnections between multiple features across two or more layers. As such, relations are project level settings and are set in Project ► Properties ► relations Relations tab. From there, you can:

  • symbologyAdd Add relation whose type can be:

    注釈

    There is no simple way yet to edit a non-polymorphic relation once it has been created. Only the name can be edited with a double-click. For any other parameters of such a relation you will have to remove and recreate it.

  • symbologyAdd Discover relations: QGIS is able to discover existing relations from supported database formats (PostgreSQL, GeoPackage, ESRI File Geodatabase, ...). This can be a good way to ease the relations definition.

  • symbologyRemove Remove relation

../../../_images/project_relations.png

図 16.102 リレーションタブ

16.4.2.1. One to many (1-N) relations

As an example you have a layer with all regions of Alaska (polygon) which provides some attributes about its name and region type and a unique id (which acts as primary key).

それから、地域にある空港の情報を持った別のポイントレイヤまたはテーブルがあり、これらの情報も把握したいとします。ほとんどの地域には複数の空港があるため、これらを地域レイヤに追加する場合は、外部キーを使って1対多のリレーションを作成する必要があります。

../../../_images/regions_with_airports.png

図 16.103 空港とアラスカの地域

Layers and keys

QGIS makes no difference between a table and a vector layer. Basically, a vector layer is a table with a geometry. So you can add your table as a vector layer. To demonstrate the 1-n relation, you can load the regions and airports layers in the sample dataset. In practice, each airport belongs to exactly one region while each region can have any number of airports (a typical one to many relation).

which has a foreign key field (fk_region) to the layer regions.

In addition to the attributes describing the airports, the aiports layer has another field fk_region which acts as a foreign key (if you have a database, you will probably want to define a constraint on it). This fk_region field will always contain an id of a region. It can be seen like a pointer to the region it belongs to.

All you have to do is to tell QGIS the relation between the layers so that you can design a custom edit form for editing and QGIS takes care of the setup. It works with different providers (so you can also use it with shape and csv files).

1対Nリレーションの定義

まず最初に行うのは、レイヤ間の関係をQGISに知らせることです。これは、 プロジェクト ► プロパティ... で行います。 リレーション タブを開き、 symbologyAdd リレーションを追加 をクリックします。

  • Name is going to be used as a title. It should be a human readable string describing what the relation is used for. We will just call say airport_relation in this case.

  • 被参照レイヤ(親) 親レイヤとも呼ばれ、プライマリキーを持っており、参照されるレイヤです。この例では、 regions レイヤです。参照レイヤの主キーを定義する必要があり、ここでは ID を指定します。

  • 参照元レイヤ(子) 子レイヤとも呼ばれ、外部キーフィールドを持ったレイヤです。この例では、 airports レイヤが該当します。参照元レイヤには他のレイヤを指す参照フィールドを指定する必要があり、ここでは fk_region とします。

    注釈

    Sometimes, you need more than a single field to uniquely identify features in a layer. Creating a relation with such a layer requires a composite key, i.e. more than a single pair of matching fields. Use the symbologyAdd Add new field pair as part of a composite foreign key button to add as many pairs as necessary.

  • Id は内部的な目的で使用され、ユニークでなければなりません。これは カスタムフォーム を作成するために必要となる場合があります。空のままにしておくと自動でIdを作成しますが、扱いやすいように自分でIdを指定することもできます。

  • リレーションの強度 は、親子レイヤ間のリレーションの強さを設定します。デフォルトの Association タイプは、親レイヤが子レイヤに 単に リンクされていることを意味します。 一方、 コンポジション タイプでは、親レイヤを複製するときに子レイヤも複製され、親レイヤの地物を削除すると子レイヤの地物も削除されます。これはすべてのレベルにカスケードしていきます(つまり、子レイヤのそのまた子レイヤ...も一緒に削除されます)。

../../../_images/regions_airports_mapping.png

図 16.104 regionsレイヤとairportsレイヤ間のリレーションの追加

リレーション タブでは、 symbologyAdd リレーションを検索 ボタンを押して、読み込んだレイヤの利用可能なリレーションをプロバイダから取得することもできます。この機能はPostgreSQLやSpatiaLiteといったデータプロバイダに保存されたレイヤで使用可能です。

1対Nリレーションのフォーム

Now that QGIS knows about the relation, it will be used to improve the forms it generates. As we did not change the default form method (autogenerated), it will just add a new widget in our form. So let's select the layer region in the legend and use the identify tool. Depending on your settings, the form might open directly or you will have to choose to open it in the identification dialog under actions.

../../../_images/airport_relation_dataview.png

図 16.105 airportsへのリレーションを持つregionsの識別ダイアログ

見ればわかるとおり、この特定の地域に割り当てられた空港が全てテーブル表示されています。また、いくつかのボタンも用意されています。早速見てみましょう。

  • toggleEditing ボタンは編集モードを切り替えるためのものです。regionsレイヤの地物の地物フォームを開いていますが、このボタンはairportsレイヤの編集モードを切り替えることに注意してください。ただしこのテーブルは、airportsレイヤの地物を表しています。

  • saveEdits ボタンは、子レイヤ(airports)の編集の全てを保存します。

  • capturePoint ボタンを使用するとマップキャンバス上でairportsレイヤのジオメトリのデジタイズを行うことができ、デフォルトで現在のregionに新しい地物を割り当てます。アイコンはジオメトリタイプによって変わることに注意してください。

  • newTableRow ボタンは、airportsレイヤの属性テーブルに新しいレコードを追加します。この新しい地物はデフォルトで現在のregionに割り当てられます。ジオメトリは、 部分を追加 デジタイジングツールを使用して後から追加できます。

  • duplicateFeature ボタンは、子レイヤ内の一つまたは複数の子地物を複製することができます。複製した子地物は後から別の親地物に割り当てることもできますし、属性値を編集することもできます。

  • deleteSelectedFeatures ボタンは、選択した空港(複数可)を永久的に削除します。

  • link シンボルをクリックすると、新しいダイアログが開き、既存の空港を選択して現在の地域に割り当てることができます。これは、誤って違う地域の上に空港を作成してしまった場合に便利です。

  • unlink シンボルは、選択した空港(複数可)を現在の地域からリンク解除し、効果的に未割り当て状態(外部キーをNULLに設定)にします。

  • zoomToSelected ボタンを押すと、選択した子地物にマップをズームさせます。

  • 右にある formViewopenTable の2つのボタンは、リレーションのある子地物の テーブル表示とフォーム表示 を切り替えます。

regionsレイヤの地物に ドラッグ&ドロップデザイナー を使用している場合には、どのツールを利用可能か選択できます。新しい地物が追加されたときに新しいフォームを開くかどうかは、 地物追加時のフォームを表示しない オプションで決めることができます。このオプションが正しく動作するためには、NULLでない属性は有効なデフォルト値をとる必要があることに注意してください。

../../../_images/airport_relation_formproperties.png

図 16.106 regionsレイヤとairportsレイヤのリレーションツールを設定するドラッグ&ドロップデザイナー

上記の例では、参照元レイヤがジオメトリを持っている(つまり、単なる英数字のテーブルではない)ので、上記の手順では、対応するジオメトリ地物を持たないエントリがレイヤの属性テーブルに作成されます。ジオメトリを追加するには、以下の操作を行います。

  1. 参照元レイヤの openTable 属性テーブルを開く を選択します。

  2. 被参照レイヤの地物フォーム内で追加したレコードを選択します。

  3. addPart 部分を追加 デジタイジングツールを使用して、選択した属性テーブルのレコードとジオメトリを結びつけます。

airportsテーブルで作業しているのなら、 fk_region フィールド(リレーションを作成するために使用するフィールド)には、「リレーションの参照」ウィジェットが自動的に設定されます。詳細は リレーションの参照ウィジェット を参照してください。

airportsレイヤのフォームには、 fk_region フィールドの右側に formView ボタンがあることがわかります。このボタンをクリックすると、regionsレイヤのフォームが開きます。このウィジェットで、簡単に素早くリンクしている親地物のフォームを開くことができます。

../../../_images/airport_attributes.png

図 16.107 regionsへのリレーションを持つairportsの識別ダイアログ

「リレーションの参照」ウィジェットには、親レイヤのフォームを子レイヤに埋め込むオプションもあります。これは、airportsレイヤの プロパティ ► 属性フォーム メニューから設定できます。 fk_region フィールドを選択して、 埋め込みフォームの表示 オプションにチェックを入れてください。

If you look at the feature dialog now, you will see that the form of the region is embedded inside the airports form and will even have a combobox, which allows you to assign the current airport to another region.

../../../_images/airport_attributes_expanded.png

さらに、airportsレイヤの編集モードを切り替えると、 fk_region フィールドにオートコンプリート機能も追加されます。入力中に regionsレイヤの id フィールドの値がすべて表示されることがわかります。ここで、airportsレイヤの プロパティ ► 属性フォーム メニューの 新しい地物の追加 オプションを選択した場合、 symbologyAdd ボタンを使用してregionsレイヤのポリゴンをデジタイズすることができます。

子レイヤは、 値による地物選択 ツールで子レイヤの属性に基づいて親レイヤの地物を選択するために使うこともできます。

図 16.108 では、空港の平均高度が海抜500mより高い地域すべてを選択しています。

フォームには多数のさまざまな集計関数があることがわかります。

../../../_images/relation_select_by_value.png

図 16.108 子レイヤの値で親レイヤの地物を選択する

16.4.2.2. Many-to-many (N-M) relations

N対Mのリレーションとは、2つのテーブル間の多数対多数の関係のことです。例えば、 airports レイヤと airlines レイヤを考えてみましょう。空港には複数の航空会社が乗り入れており、航空会社は複数の空港に乗り入れています。

This SQL code creates the three tables we need for an N-M relationship in a PostgreSQL/PostGIS schema named locations. You can run the code using the Database ► DB Manager… for PostGIS or external tools such as pgAdmin. The airports table stores the airports layer and the airline table stores the airlines layer. In both tables few fields are used for clarity. The tricky part is the airports_airlines table. We need it to list all airlines for all airports (or vice versa). This kind of table is known as a pivot table. The constraints in this table force that an airport can be associated with an airline only if both already exist in their layers.

CREATE SCHEMA locations;

CREATE TABLE locations.airports
(
   id serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   airport_name text NOT NULL,
   CONSTRAINT airports_pkey PRIMARY KEY (id)
);

CREATE INDEX airports_geom_idx ON locations.airports USING gist (geom);

CREATE TABLE locations.airlines
(
   id serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   airline_name text NOT NULL,
   CONSTRAINT airlines_pkey PRIMARY KEY (id)
);

CREATE INDEX airlines_geom_idx ON locations.airlines USING gist (geom);

CREATE TABLE locations.airports_airlines
(
   id serial NOT NULL,
   airport_fk integer NOT NULL,
   airline_fk integer NOT NULL,
   CONSTRAINT airports_airlines_pkey PRIMARY KEY (id),
   CONSTRAINT airports_airlines_airport_fk_fkey FOREIGN KEY (airport_fk)
      REFERENCES locations.airports (id)
      ON DELETE CASCADE
      ON UPDATE CASCADE
      DEFERRABLE INITIALLY DEFERRED,
   CONSTRAINT airports_airlines_airline_fk_fkey FOREIGN KEY (airline_fk)
      REFERENCES locations.airlines (id)
      ON DELETE CASCADE
      ON UPDATE CASCADE
      DEFERRABLE INITIALLY DEFERRED
 );

PostgreSQLの代わりに、GeoPackageを使うこともできます。この場合には、3つのテーブルは データベース ► DBマネージャ… を使用して手動で作成します。GeoPackageにはスキーマが無いため、 locations の接頭辞は不要です。

airports_airlines テーブルの外部キー制約は、 テーブル ► テーブルを作成…テーブル ► テーブルの編集… では作成することができません。このため、このテーブルは データベース ► SQLウィンドウ… を使用して作成する必要があります。GeoPackageは ADD CONSTRAINT 文をサポートしていないため、 airports_airlines テーブルは2段階で作成する必要があります。:

  1. テーブル ► テーブルを作成… を使用して、 id フィールドのみを持つテーブルを準備します。

  2. データベース ► SQLウィンドウ… を使用して、以下のSQLコードを入力し実行します:

    ALTER TABLE airports_airlines
       ADD COLUMN airport_fk INTEGER
       REFERENCES airports (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE
       DEFERRABLE INITIALLY DEFERRED;
    
    ALTER TABLE airports_airlines
       ADD COLUMN airline_fk INTEGER
       REFERENCES airlines (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE
       DEFERRABLE INITIALLY DEFERRED;
    

それから、上で説明したようにQGISで2つの 1対多のリレーション を設定します。

  • airlines テーブルとピボットテーブルの間のリレーション

  • airports テーブルとピボットテーブルとの間の第2のリレーション

これを行うためのより簡単な方法(PostgreSQLのみ)は、 プロジェクト ► プロパティ ► リレーションリレーションを検索 を使用することです。QGISは自動的にデータベース内の全てのリレーションを読み込むので、必要な2つのリレーションを選択するだけで設定ができます。最初にQGISプロジェクトに3つのテーブルを読み込むことを忘れないようにしてください。

../../../_images/airports_airlines_relation.png

図 16.109 リレーションと自動検索

airportairline を削除する場合、QGISは airports_airlines テーブルの関連するレコードを削除しません。この作業は、現在の例のようにピボットテーブルの作成時に正しい 制約 を指定すれば、データベースによって行われます。

注釈

N対Mのリレーションと自動トランザクショングループを組み合わせる

このようなコンテキストで作業する場合は、 プロジェクトのプロパティ ► データソース► でトランザクションモードを有効にする必要があります。 QGISは、すべてのテーブル(航空会社、空港、ピボットテーブル)の行を追加または更新できる必要があります。

最後に、 レイヤプロパティ ► 属性フォーム で、 airports レイヤと airlines レイヤに対して正しい「要素数」を選択する必要があります。最初のレイヤには airlines (id) オプションを、2番目のレイヤには airports (id) オプションを選択する必要があります。

../../../_images/airports_airlines_relation_formproperties.png

図 16.110 関係の要素数の設定

これで、サブフォーム内で 子地物の追加既存の子地物をリンク を使用してairlineにairportを(そしてairportにairlineを)関連付けることができるようになりました。 airports_airlines テーブルにはレコードが自動的に挿入されます。

../../../_images/add_airport_airline.png

図 16.111 airportsとairlinesのN対Mリレーション

注釈

多対1リレーション 要素数を使用する

Sometimes hiding the pivot table in an N-M relationship is not desirable. Mainly because there are attributes in the relationship that can only have values when a relationship is established. If your tables have a geometry field, it could be interesting to activate the On map identification option (Layer Properties ► Attributes Form ► Available widgets ► Fields) for the foreign key fields in the pivot table.

注釈

ピボットテーブルの主キー

Avoid using multiple fields in the primary key in a pivot table. QGIS assumes a single primary key so a constraint like constraint airports_airlines_pkey primary key (airport_fk, airline_fk) will not work.

16.4.2.3. Polymorphic relations

The purpose

多態リレーションは1-N関係の特殊なケースであり、1つの参照元(ドキュメント)レイヤ内に複数の参照先レイヤの地物が含まれます。これは、参照先レイヤごとに異なる参照元レイヤを必要とする通常のリレーションとは異なっています。参照元(ドキュメント)レイヤに layer_field カラムを追加することで単一の参照元(ドキュメント)レイヤとすることができ、ここには参照先レイヤを識別する情報を格納します。最も単純な形は、参照元(ドキュメント)レイヤはこのフィールドに参照先レイヤのレイヤ名を入れるだけです。

より正確に言うならば、多態リレーションは、参照元レイヤが同じ通常のリレーションの集合ですが、参照先レイヤは動的に定義されるものです。レイヤの多態リレーションの設定は、テーブル名、レイヤID、レイヤ名など、参照先レイヤのいくつかのプロパティと一致しなければならない式を使用することで解決されます。

公園に行き、そこで見かけたさまざまな種類の植物 plants や動物 animals の写真を撮ることを考えてみましょう。それぞれの植物や動物には複数の写真が関連付けられているので、通常の 1:N リレーションで写真を保存する場合、 animal_imagesplant_images という2つの別々のテーブルが必要です。テーブル2つならば問題とはならないかもしれませんが、キノコや鳥などの写真も別々に撮影したいとしたらどうでしょうか。

多態リレーションは、参照元のすべての地物を同一の documents テーブルに格納することでこの問題を解決します。各地物の referenced_layer フィールドには参照先レイヤが、 referenced_fk フィールドには参照先の地物ID が格納されます。

多態リレーションの定義

最初に、QGISにレイヤ間の多態リレーションについて知らせましょう。これは、 プロジェクト ► プロパティ... から行えます。 リレーション タブを開き、 symbologyAdd リレーションを追加 ボタンの横にある小さな下向き矢印のボタンをクリックします。新しく現れたドロップダウンメニューから、 多態リレーションを追加 オプションを選択します。

../../../_images/polymorphic_relation_properties.png

図 16.112 参照元レイヤとして documents を、参照先レイヤとして animalsplants を使用した多態リレーションを追加します。

  • Id は内部的な目的で使用され、ユニークでなければなりません。これは カスタムフォーム を作成するために必要となる場合があります。空のままにしておくと自動でIdを作成しますが、扱いやすいように自分でIdを指定することもできます。

  • 参照元レイヤ(子) は子レイヤとも呼ばれ、外部キーのフィールドを持っているレイヤです。この例では documents レイヤです。このレイヤには他のレイヤを指す参照フィールドを追加する必要があり、これが referenced_fk です。

    注釈

    Sometimes, you need more than a single field to uniquely identify features in a layer. Creating a relation with such a layer requires a composite key, i.e. more than a single pair of matching fields. Use the symbologyAdd Add new field pair as part of a composite foreign key button to add as many pairs as necessary.

  • レイヤのフィールド は、評価されたレイヤ式の結果を格納する参照元テーブルのフィールドです。これは、この地物がどのレイヤに属するかの参照テーブルです。 この例では、 referenced_layer フィールドがこれに該当します。

  • レイヤのフィールド式 は、レイヤのユニークな識別子を評価します。これは、レイヤ名 @layer_name やレイヤのID @layer_id 、レイヤのテーブル名 decode_uri(@layer, 'table') など、レイヤを一意に識別できるものであれば何でも利用できます。

  • リレーションの強度 は、親子レイヤ間に生成されたリレーションの強さを設定します。デフォルトの Association タイプは、親レイヤが子レイヤに 単に リンクされていることを意味します。 一方、 コンポジション タイプでは、親レイヤを複製するときに子レイヤも複製され、親レイヤの地物を削除すると子レイヤの地物も削除されます。これはすべてのレベルにカスケードしていきます(つまり、子レイヤのそのまた子レイヤ...も一緒に削除されます)。

  • 参照先レイヤ は親レイヤとも呼ばれ、主キーを持ち、指し示される側のレイヤです。この例では、 plants レイヤと animals レイヤがこれに該当します。参照先レイヤの主キーをドロップダウンメニューから定義する必要があり、この例では fid です。有効な主キーを定義するには、全ての参照先レイヤで同じ名前のフィールドが存在する必要があることに注意してください。そのようなフィールドが存在しない場合には、多態リレーションを保存することができません。

一度追加したら、この多態リレーションは 多態リレーションを編集 メニューエントリから編集ができます。

../../../_images/polymorphic_relations.png

図 16.113 Preview of the newly created polymorphic relation and its child relations for animals and plants.

上記の例では、以下のデータベーススキーマを使用しています:

CREATE SCHEMA park;

CREATE TABLE park.animals
(
   fid serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   animal_species text NOT NULL,
   CONSTRAINT animals_pkey PRIMARY KEY (fid)
);

CREATE INDEX animals_geom_idx ON park.animals USING gist (geom);

CREATE TABLE park.plants
(
   fid serial NOT NULL,
   geom geometry(Point, 4326) NOT NULL,
   plant_species text NOT NULL,
   CONSTRAINT plants_pkey PRIMARY KEY (fid)
);

CREATE INDEX plants_geom_idx ON park.plants USING gist (geom);

CREATE TABLE park.documents
(
   fid serial NOT NULL,
   referenced_layer text NOT NULL,
   referenced_fk integer NOT NULL,
   image_filename text NOT NULL,
   CONSTRAINT documents_pkey PRIMARY KEY (fid)
);