DBの技術本「Effective SQL RDMSのパフォーマンスを最大限引き出す61の手法と思考」の内容から質問です。
この場で質問すべきかどうか迷ったのですが、該当のコードがGitHubのpublicで公開されているため、掲載いたしました。
チームの一覧からCLOSS JOIN
で総当たり戦を作成し、かつホーム・アウェイを同数にする
という課題からの質問です。
コードは以下になります。(PostgreSQL)
【CREATE】
CREATE TABLE Teams ( TeamID int NOT NULL DEFAULT 0 , TeamName varchar (50) NOT NULL , CaptainID int NULL );
【INSERT】
合計10のTeamを作成します。
INSERT INTO Teams (TeamID, TeamName, CaptainID) VALUES (1, 'Marlins', 2); INSERT INTO Teams (TeamID, TeamName, CaptainID) VALUES (2, 'Sharks', 5);
【SELECT】
WITH TeamPairs AS (SELECT ROW_NUMBER() OVER (ORDER BY Teams1.TeamID, Teams2.TeamID) AS GameSeq, Teams1.TeamID AS Team1ID, Teams1.TeamName AS Team1Name, Teams2.TeamID AS Team2ID, Teams2.TeamName AS Team2Name FROM Teams AS Teams1 CROSS JOIN Teams AS Teams2 WHERE Teams2.TeamID > Teams1.TeamID) SELECT TeamPairs.GameSeq, CASE MOD(ROW_NUMBER() OVER (PARTITION BY TeamPairs.Team1ID ORDER BY GameSeq),2 ) WHEN 0 THEN CASE MOD(RANK() OVER (ORDER BY TeamPairs.Team1ID), 3) WHEN 0 THEN 'Home' ELSE 'Away' END ELSE CASE MOD(RANK() OVER (ORDER BY TeamPairs.Team1ID), 3) WHEN 0 THEN 'Away' ELSE 'Home' END END AS Team1PlayingAt, TeamPairs.Team1ID, TeamPairs.Team1Name, TeamPairs.Team2ID, TeamPairs.Team2Name FROM TeamPairs ORDER BY TeamPairs.GameSeq;
わからないのはこの部分です。
CASE MOD(ROW_NUMBER() OVER (PARTITION BY TeamPairs.Team1ID ORDER BY GameSeq),2 ) WHEN 0 THEN CASE MOD(RANK() OVER (ORDER BY TeamPairs.Team1ID), 3) WHEN 0 THEN 'Home' ELSE 'Away' END ELSE CASE MOD(RANK() OVER (ORDER BY TeamPairs.Team1ID), 3) WHEN 0 THEN 'Away' ELSE 'Home' END END AS Team1PlayingAt,
解説はこのようになっていました。
・メインのクエリを1つおきに調べて(MOD 2)1つ目のチームにホーム・アウェイのどちらを割り当てるか決定している。
・各チームの最初のゲームには、ホームが割り当てられる傾向にある。
・そのため3つ目の行を調べて割り当てが逆の順序になるようにしている。(そうしないとホームが25、アウェイが20になってしまう。)
特にわからないのは3つ目の行
です。MOD 3
の部分だと思いますが、この判定が何を意味しているのかわかりません。
解決のヒントがあれば、ご回答いただければ幸いです。