web-dev-qa-db-ja.com

ビューとしての再帰的な親子位置関係キャッシュ

これが私のデータ構造です:

CREATE TABLE Locations(
    LocID int IDENTITY(1,1) NOT NULL,
    LocationTypeID int NOT NULL,
    ParentID int NULL,
    LocNum varchar(50) NULL,
    LocName varchar(250) NULL,
)
CREATE TABLE LocationTypes(
    LocationTypeID int IDENTITY(1,1) NOT NULL,
    TypeName varchar(50) NOT NULL
)

LocationTypesテーブルには、次の値が含まれています。

+----------------+----------+
| LocationTypeID | TypeName |
+----------------+----------+
|              1 | Campus   |
|              2 | Building |
|              3 | Area     |
|              4 | Floor    |
|              5 | Room     |
+----------------+----------+

Locationsテーブルには、ParentIDがnull(キャンパス)である場所や、ParentIDがある場所など、さまざまな場所が含まれています。 LocationTypesテーブルに示されているように、データ構造には5つのレベルの階層があります。キャンパス(1)は最も限定的ではなく、ルーム(5)は最も限定的です。私のデータベースにはLocIDを参照する他のテーブルがありますが、ほとんどの場合、これらのテーブルはLocationTypeID5の場所を参照していますが、常にそうではありません。

エンドユーザーに表示するために、階層内のすべての場所の名前を取得する必要があります。

最終的に取得したいのは、次の構造を持つビュー(またはキャッシュされたテーブル)です。

+-------+---------------+-----------------+-------------+--------------+-------------+
| LocID | CampusLocName | BuildingLocName | AreaLocName | FloorLocName | RoomLocName |
+-------+---------------+-----------------+-------------+--------------+-------------+

LocationTypeID5以外のLocationsの場合、これらの列の一部がnullになることに気づきましたが、これはまったく問題ありません。

私はおそらく再帰的な共通テーブル式が必要であることを知っています。

基本的に、このための疑似コードロジックは次のとおりです。

  • LocationのForeach LocationsTable
  • LocationParent Locationを取得し、親がなくなるまで再帰的に続行します
  • このキャッシュされたデータをビューに保存して、LocIDを参照する他のテーブルで簡単にLEFT JOINedできるようにします。

すべてが理にかなっていることを願っています。私を助けることができる人に感謝します。

1
David Allen

私はあなたがこのクエリで望ましい結果を達成できると信じています:

;WITH CTE_Locations (LocID, CampusLocName, BuildingLocName, AreaLocName, FloorLocName, RoomLocName)
AS
(
    SELECT LocID, 
        LocName AS CampusLocName, 
        CONVERT(varchar(250), NULL) AS BuildingLocName, 
        CONVERT(varchar(250), NULL) AS AreaLocName, 
        CONVERT(varchar(250), NULL) AS FloorLocName, 
        CONVERT(varchar(250), NULL) AS RoomLocName
    FROM Locations
    WHERE ParentID IS NULL

    UNION ALL

    SELECT L.LocID, 
        CampusLocName, 
        IIF(L.LocationTypeID = 2, LocName, BuildingLocName) AS BuildingLocName, 
        IIF(L.LocationTypeID = 3, LocName, AreaLocName) AS AreaLocName, 
        IIF(L.LocationTypeID = 4, LocName, FloorLocName) AS FloorLocName, 
        IIF(L.LocationTypeID = 5, LocName, RoomLocName) AS RoomLocName
    FROM Locations L
        INNER JOIN CTE_Locations CTE ON L.ParentID = CTE.LocID 
)
SELECT LocID, CampusLocName, BuildingLocName, AreaLocName, FloorLocName, RoomLocName
FROM CTE_Locations;

WITH common_table_expression docによると:

この句は、定義するSELECTステートメントの一部としてCREATE VIEWステートメントでも使用できます。

1
Ronaldo