これはもうあかん。この問題は本当によーわからん。なので検証します。
【問題】
DRAG DROP
You query a database that includes two tablesこの二つのテーブルを含むデータベースのクエリを作ります: ProjectとTask.
The Project table includes the following columns: Projectテーブルは以下のコラムを含みます。
Task level is defined using the following rules: Taskのレベルわけは以下のようなルールで行います。
Task.ProjectIdは、もし『NULL』だったらTaskにProjectがアサインされていないということらしい。そして、『ParentTaskId』とあるのが、それぞれのTaskにParentTaskがあるかないかだそうだ。
『Task』に『ParentTask』がない場合は、『TaskLevel』=0、あれば『TaskLevel』=『ParentTaskLevel』+1
You need to determine the task level for each task in the hierarchy. それぞれの『TaskLevel』を階級順にはっきりさせてください。←これが問題の主旨です。
Which five Transact-SQL segments should you use to develop the solution? 全部で7つのうち、5つ選んでステートメントを作ってもらいます。
【推測】
恐ろしい。。。ここに『Projectテーブル』が使われている形跡がない。。。そんなこと言っても始まらない。
まず、『With』とついているんで、これはCTEにせいということですね。
① With TaskWithLevel(ParentTaskId, TaskId, TaskName,TaskLevel) AS (
そしてこれを必ず完結させるためには、もうひとつ『)』終わるカッコが必要で、チョイスはこれだけ。
② )
Select * from TaskWithLevel
さあて、次が勝負。
CTEの意味がはっきりと分からなくても、このCTEの名前である『TaskWithLevel』を使っているものはCTEの中に挿入できない。CTEの『AS()』に入るステートメントを必要としているので、
③ SELECT CAST(NULL AS int) AS ParentTaskId, T.TaskId, T.TaskName, 0 AS TaskLevel
FROM Task T
WHERE T.ParentTaskId IS NULL
④ SELECT T.TaskId AS ParentTaskId, CAST(null AS int) AS TaskId, T.TaskName, 0 AS TaskLEvel
FROM Task T
WHERE T.ParentTaskId IS NULL
のふたつとなる。けど、④の「WHERE T.ParentTaskId IS NULL」でTaskIdまで「CAST(null AS int) AS TaskId」されてNULLじゃ、Taskが存在しないことになるよね。だからないな。
とりあえず、②の『) Select * from TaskWithLevel』の後がもし必要だとしたら、唯一実際にこのCTEの『TaskWithLevel』を使っている部分です。だから、
⑤ SELECT R.TaskId AS ParentTaskId, T.TaskId, T.TaskName,R.TaskLevel+1 AS TaskLevel
FROM Task T INNER JOIN TaskWithLevel R ON T.ParentTaskId = R.TaskId
「全部で5つつかう」ということなので、数的にはこれが必要になるでしょうね。
残りは⑥UNION, ⑦UNION ALLとなります。
では、①と②のCTEの受け皿がはっきりとしているので、中身を検証しましょう。
「『ParentTask』がない場合は『TaskLevel』=0、『ParentTask』がある場合は『TaskLevel』=『ParentTaskLevel』+1」とあるので、
③ SELECT CAST(NULL AS int) AS ParentTaskId, T.TaskId, T.TaskName, 0 AS TaskLevel
FROM Task T
WHERE T.ParentTaskId IS NULL
➞『TaskLevel』=0ParentTaskなしなので、『UNION/UNION ALL』は『NULL』もカウントしてくれるので、ParentTaskIdが『NULL』としてCASTされてよいじゃないか。
【シナリオ構築】
①With TaskWithLevel(ParentTaskId, TaskId, TaskName,TaskLevel) AS (
②SELECT CAST(NULL AS int) AS ParentTaskId, T.TaskId, T.TaskName, 0 AS TaskLevel
FROM Task T
WHERE T.ParentTaskId IS NULL
③)
Select * from TaskWithLevel
④UNION
⑤SELECT R.TaskId AS ParentTaskId, T.TaskId, T.TaskName,R.TaskLevel+1 AS TaskLevel
FROM Task T INNER JOIN TaskWithLevel R ON T.ParentTaskId = R.TaskId
1.まずはUNIONはコラムのデータタイプ、数が同じで、初めてユニークデータを両テーブルからとれるので、これをチェック。
CTE: Select * from TaskWithLevel
ParentTaskId=NULL
TaskId=Task.TaskId
TaskName=Task.TaskName
TaskLevel=Task.TaskLevel
INNER JOIN TaskWithLevel:
TaskId=ParentTaskId
TaskId=Task.TaskId
TaskName=Task.TaskName
TaskLevel=TaskLevel+1
良い感じですね。
2.ルールをあてはめてみる。
A.「ひとつはProjectテーブル用のユニークID、もう一つはもし『NULL』だったら、TaskにProjectがアサインされていないということらしい。』
『ProjectId』完全に避けてSELECT文どころが、どこにも見当たらないので、これは無視します。このテスト(70-761)、難ありデータ構造をわざと使ってることが結構あります。。。
B.「『ParentTask』なければ『TaskLevel』=0、あれば『TaskLevel』=『ParentTaskLevel』+1」
「CTE:」が『ParentTask』なければ『TaskLevel』=0にあたいする。
「INNER JOIN TaskWithLevel:」が『ParentTask』があれば『TaskLevel』=『ParentTaskLevel』+1あたいする。
ってことかな?
3.『UNION』?『UNION ALL』?
これはわからん。。。
【ググった結果】
(Peterさん、毎度ありがとうございます。勉強になります。)
https://www.briefmenow.org/microsoft/which-five-transact-sql-segments-should-you-use-to-deve-2/
ねこの答え |
ググった中で大多数の答え |
WITH TaskWithLevel (TaskID, TaskName, ParentTaskID, TaskLevel)
AS (
SELECT T.TaskID,T.TaskName,CAST(NULL AS INT) AS ParentTaskID,0 AS TaskLevel FROM dbo.Task AS T WHERE ParentTaskID IS NULL
) SELECT * FROM TaskWithLevel ORDER BY TaskName
UNION
SELECT T.TaskID,T.TaskName,R.TaskID AS ParentTaskID,(R.TaskLevel + 1) AS TaskLevel FROM dbo.Task AS T INNER JOIN TaskWithLevel AS R ON T.ParentTaskID = R.TaskID
|
WITH TaskWithLevel (TaskID, TaskName, ParentTaskID, TaskLevel)
AS (
SELECT T.TaskID,T.TaskName,CAST(NULL AS INT) AS ParentTaskID,0 AS TaskLevel FROM dbo.Task AS T WHERE ParentTaskID IS NULL
UNION ALL
SELECT T.TaskID,T.TaskName,R.TaskID AS ParentTaskID,(R.TaskLevel + 1) AS TaskLevel FROM dbo.Task AS T INNER JOIN TaskWithLevel AS R ON T.ParentTaskID = R.TaskID
) SELECT * FROM TaskWithLevel ORDER BY TaskName
|
どなたか、どっちが正しいか教えてください。。。
でももうすぐで『Exam4Training』合計168問終わるからね。あと48問!!!今日中におわらせるぞ!!!
*注意、結構間違っている答えがたくさんあります。気をつけてください。