質問は非常に広範囲です。この特定のテーブルは、階層を生成する過程で使用される現在の列が行を返さない場合は、次の列を選択するクエリ
:私は、以下の構造を有する単一のマッピングテーブルを有しています。テーブル内の列の順序と位置は、階層(組織、カテゴリ、大陸、国など)の順番を示します。この階層の各エンティティには、関連テーブルId
とName
が関連付けられています。たとえば、CountryId
とCountryName
という表があります。Country
テーブルがあります。 MappingTableの値はすべてnullableであるため、の外部キー制約はありませんです。
私は、次の手順を実行します手順を生成したい:提供条件に基づいて
、階層内の次のエンティティの値を取得します。例えば、OrganizationId
とCategoryId
が与えられている場合、上記の条件を満たすContinentId
の値を検索する必要があります。
また、ContinentId
の値がNULL
の場合は、CountryId
の値を取得する必要があります。ここで、条件がOrganizationId = 1 and CategoryId = 1
である場合、手順はRegionId
のリストを返すべきです。
RegionId
の検索に加えて、対応するRegionName
をRegion
テーブルから取得する必要があります。
これまでの手順は、このようになります。ここで説明するにはいくつかのことがあります。
ALTER PROCEDURE [dbo].[GetHierarchy]
(
@MappingTableName VARCHAR(30),
@Position VARCHAR(5),
-- Given in the form of Key-value pairs 'OrganizationId:1,CategoryId:1'
@InputData VARCHAR(MAX),
@Separator CHAR(1),
@KeyValueSeperator CHAR(1)
)
AS
BEGIN
DECLARE @Sql NVARCHAR(MAX)
DECLARE @Result NVARCHAR(MAX)
DECLARE @Sql1 NVARCHAR(MAX);
DECLARE @TableName NVARCHAR(30)
DECLARE @Exists bit
SELECT @TableName = COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @MappingTableName AND ORDINAL_POSITION = @position
SET @TableName = SUBSTRING(@TableName,0,LEN(@TableName) - 1)
-- Returns a dynamic query like "SELECT ContinentId from Continent WHERE OrganizationId = 1 and CategoryId = 1".
SELECT @Sql = [dbo].[KeyValuePairs](@TableName, @InputData, @Separator, @KeyValueSeperator)
SET @Sql1 = N'SET @Exists = CASE WHEN EXISTS(' + @Sql + N' AND ' + @TableName + N'Id IS NOT NULL) THEN 1 ELSE 0 END'
PRINT @Sql
EXEC sp_executesql @Sql1,
N'@Exists bit OUTPUT',
@Exists = @Exists OUTPUT
IF(@Exists = 1)
BEGIN
SET @Sql1 = 'SELECT ' + @TableName + 'Id, ' + @TableName + 'Name FROM '+ @TableName+' WHERE ' + @TableName +'Id IN (' + @Sql + ')';
PRINT @Sql1
EXECUTE sp_executesql @SQL1
END
ELSE
BEGIN
--PRINT 'NOT EXISTS'
DECLARE @nextPosition INT
SELECT @nextPosition = CAST(@position AS INT)
SET @nextPosition = @nextPosition + 1
SET @Position = CONVERT(VARCHAR(5), CAST(@position AS INT))
EXEC [dbo].[GetHierarchy] @MappingTableName, @Position, @InputData, @Separator, @KeyValueSeperator
END
END
この手順のロジックは、私は(ここでは、それはContinent
ある条件に基づいて)特定の位置で列の名前を取得し、ベースの次の列の値を取得するために、動的なクエリを生成するようなものです(私はこれを行うために別の関数を使用しています)。 一度取得すると、問合せを実行して、行を戻すかどうかを確認します。クエリで行が返された場合は、対応するContinentName
をContinent
テーブルから取得します。行が返されない場合は、次の位置を入力として再帰的にプロシージャを呼び出します。
物事のビジネス面では、2段階のプロセスのようです。しかし、手続きとして、それは非常に複雑で、広範で、再帰的ではありません。これを行う簡単な方法はありますか?私はCTEに精通していません - CTEを使用して同じロジックを実装できますか?
これは、ここで求められているものと非常によく似ています:Working with a dynamic hierarchy SQL Server