「タグ」と「タスク」の間にテーブルの関係があります。 M:Mです。関係はテーブル 'TagTaskMapping'にマップされます。
TagAssignmentテーブルは、タグと日付の関係を格納します。したがって、タグを単一の日付(期間)にマップできます。
SQLからネストされた階層を出力したい。
SQLテーブル:
-- tag assigned to a specific date
CREATE TABLE [dbo].[TagAssignment](
[TagAssignmentID] [int] IDENTITY(1,1) NOT NULL,
[TagID] [int] NOT NULL,
[Period] [date] NOT NULL
);
-- task(s) mapped to tag(s)
CREATE TABLE [dbo].[TagTaskMapping](
[TagID] [int] NOT NULL,
[TaskID] [int] NOT NULL
);
-- tag table
CREATE TABLE [dbo].[Tag](
[TagID] [int] IDENTITY(1,1) NOT NULL,
[TagName] [nvarchar](150) NOT NULL
)
TagAssignmentマッピングテーブルデータ:
TagAssignmentID TagID Period
24 3 31/05/2017
14 2 31/05/2017
TagTaskMappingテーブルデータ:
TagID TaskID
2 1
2 2
2 3
3 1
3 3
これが私のquery ...です.
DECLARE @Period datetime = '2017-05-31'
;WITH CTE_TagAssignment
AS
(
-- GET TAG(S) Assigned to selected PERIOD
SELECT
ta.TagID
,t.TagName
,null as 'Task'
FROM dbo.TagAssignment ta
INNER JOIN
dbo.Tag t
ON t.TagID = ta.TagID
WHERE ta.Period = @Period
UNION ALL
/**USING RECURSION!!!!**/
-- foreach above tag assigned to a period, get it's associated task(s)
SELECT
ttm.TagID
,null AS 'TagName'
,ttm.TaskID as 'Task'
FROM CTE_TagAssignment cta
INNER JOIN
dbo.TagTaskMapping ttm
ON cta.TagID = ttm.TagID
)
SELECT *
FROM CTE_TagAssignment
OPTION (MAXRECURSION 100);
ただし、次のエラーが発生します:ステートメントが終了しました。ステートメントが完了する前に、最大再帰100を使い果たしました。
これが階層ですoutput希望します...
TagID TagName Task
2 Level 5
1
2
3
3 Level 3
1
3
再帰的なソリューションを必要としない私見では、単純なJOINを使用してそれを得ることができます。
DECLARE @Period datetime = '20170531'; SELECT t.TagID, t.TagName, tm.TaskID FROM TagAssignment ta INNER JOIN TagTaskMapping tm ON tm.TagID = ta.TagID INNER JOIN Tag t ON t.TagID = tm.TagID WHERE ta.Period = @period ORDER BY tm.TagID, tm.TaskID; GO
TagID | TagName | TaskID ----:| :--- -----: 2 |レベル5 | 1 2 |レベル5 | 2 2 |レベル5 | 3 3 |レベル3 | 1 3 |レベル3 | 3
dbfiddle ---(ここ
注:これは基本的に、McNetsのソリューションのバリエーションであり、要求したフォーマットとCTEに関する問題の説明が含まれています。
McNetsが指摘しているように、実際には再帰クエリはありません。再帰CTEでは、通常、クエリの再帰部分に何らかの条件があり、強制的に停止します。最終的には、行を生成しない一連の値に遭遇します。あなたはそのような停止条件を持っていません。新しい行を繰り返し生成し続けるだけです。
あなたの本当の問題はフォーマットの問題です。
これにより、必要な結果が必要な形式で取得されます。
SELECT CASE WHEN Header = 1 THEN CAST(TagID as varchar(20)) ELSE '' END as TagID
,CASE WHEN Header = 1 THEN TagName ELSE '' END as TagName
,CASE WHEN Header = 1 THEN '' ELSE CAST(TaskId as varchar(20)) END as TaskID
FROM (
SELECT DISTINCT
t.TagID, t.TagName, CAST(NULL as int) as TaskID, 1 as Header
FROM TagAssignment ta
INNER JOIN TagTaskMapping tm ON ta.TagID = tm.TagID
INNER JOIN Tag t ON ta.TagID = t.TagID
WHERE ta.Period = @period
UNION ALL
SELECT t.TagID, t.TagName, tm.TaskID, 0 as Header
FROM TagAssignment ta
INNER JOIN TagTaskMapping tm ON ta.TagID = tm.TagID
INNER JOIN Tag t ON ta.TagID = t.TagID
WHERE ta.Period = @period
) sq
ORDER BY sq.TagID, Header DESC, sq.TaskID;
dbfiddle を確認します(ここでも、McNetsによって行われた作業に基づいています)。