将棋のタイトル獲得期数の話をしていると、「昔はタイトル戦自体が少なかったから」「タイトル戦が3つしかなかった時代の大山先生が今の8つ時代ならいくつ獲っただろうね」という話題になることも多いですね。じゃぁ、年4つの時代に4つとも獲れば(今で言うところの)8個相当、というように重み付けをしてみたらどうなるんだろう、と試してみた日記です。
もちろんタイトル戦が多くなれば日程が詰まって準備の時間が少なくなるとか疲労がたまるとか、まったく条件が同じというわけではありませんが、お遊びとしてお付き合いいただけたらと思います。
データの用意
ネットで公開されているタイトル保持者データを、Excelとテキストファイルを駆使してかなり泥臭く手作業で加工してデータを作りました。できあがったデータはこんな感じで、テーブルに登録。今回は集計のお遊びをするだけのデータなので、正規化とかどうでもいいの。
mysql> select * FROM titleholder LIMIT 5; +------+--------+--------------+------------+ | year | zenkou | kisi_name | title_name | +------+--------+--------------+------------+ | 2022 | | 藤井聡太 | 叡王戦 | | 2021 | | 藤井聡太 | 叡王戦 | | 2020 | | 豊島将之 | 叡王戦 | | 2019 | | 永瀬拓矢 | 叡王戦 | | 2018 | | 髙見泰地 | 叡王戦 | +------+--------+--------------+------------+
件数は、469件あります。
mysql> SELECT COUNT(*) FROM titleholder; +----------+ | COUNT(*) | +----------+ | 469 | +----------+
年ごとのタイトル戦の数の変遷
以下のようになります。2022年はまだ3つしか実施されていないので「3」と出ています(その年のタイトル獲得者データなので、未実施のタイトル戦のデータはないため)。なお、棋聖戦が年2回実施されていた時期は、それらを「その年に2個のタイトル」としてカウントしています。1977年がひとつ減ったのは「名人戦未開催」が数字として表れているものですね。
mysql> SELECT year, count(*) cnt FROM titleholder GROUP BY year ORDER BY year; +------+-----+ | year | cnt | +------+-----+ | 1937 | 1 | | 1940 | 1 | | 1942 | 1 | | 1944 | 1 | | 1945 | 1 | | 1947 | 1 | | 1948 | 1 | | 1949 | 1 | | 1950 | 2 | | 1951 | 3 | | 1952 | 3 | | 1953 | 3 | | 1954 | 3 | | 1955 | 3 | | 1956 | 3 | | 1957 | 3 | | 1958 | 3 | | 1959 | 3 | | 1960 | 4 | | 1961 | 4 | | 1962 | 5 | | 1963 | 6 | | 1964 | 6 | | 1965 | 6 | | 1966 | 6 | | 1967 | 6 | | 1968 | 6 | | 1969 | 6 | | 1970 | 6 | | 1971 | 6 | | 1972 | 6 | | 1973 | 6 | | 1974 | 6 | | 1975 | 7 | | 1976 | 7 | | 1977 | 6 | | 1978 | 7 | | 1979 | 7 | | 1980 | 7 | | 1981 | 7 | | 1982 | 7 | | 1983 | 8 | | 1984 | 8 | | 1985 | 8 | | 1986 | 8 | | 1987 | 8 | | 1988 | 8 | | 1989 | 8 | | 1990 | 8 | | 1991 | 8 | | 1992 | 8 | | 1993 | 8 | | 1994 | 8 | | 1995 | 7 | | 1996 | 7 | | 1997 | 7 | | 1998 | 7 | | 1999 | 7 | | 2000 | 7 | | 2001 | 7 | | 2002 | 7 | | 2003 | 7 | | 2004 | 7 | | 2005 | 7 | | 2006 | 7 | | 2007 | 7 | | 2008 | 7 | | 2009 | 7 | | 2010 | 7 | | 2011 | 7 | | 2012 | 7 | | 2013 | 7 | | 2014 | 7 | | 2015 | 7 | | 2016 | 7 | | 2017 | 7 | | 2018 | 8 | | 2019 | 8 | | 2020 | 8 | | 2021 | 8 | | 2022 | 3 | +------+-----+ 81 rows in set (0.00 sec)
今までタイトルホルダーになった人は何人
シンプルに集計
mysql> SELECT COUNT(DISTINCT kisi_name) ninzu FROM titleholder; +-------+ | ninzu | +-------+ | 45 | +-------+
タイトル獲得期数ランキング
まずは重み付けを行わずに、実際に獲得したタイトルの数を集計してみます。羽生先生99期、大山先生80期、ソータ先生9期、と正しそうな結果が得られました。
mysql> SELECT kisi_name, COUNT(*) cnt FROM titleholder GROUP BY kisi_name ORDER BY cnt DESC; +-----------------+-----+ | kisi_name | cnt | +-----------------+-----+ | 羽生善治 | 99 | | 大山康晴 | 80 | | 中原誠 | 64 | | 渡辺明 | 31 | | 谷川浩司 | 27 | | 米長邦雄 | 19 | | 佐藤康光 | 13 | | 森内俊之 | 12 | | 藤井聡太 | 9 | | 木村義雄 | 8 | | 加藤一二三 | 8 | | 升田幸三 | 7 | | 南芳一 | 7 | | 久保利明 | 7 | | 豊島将之 | 6 | | 塚田正夫 | 6 | | 郷田真隆 | 6 | | 高橋道雄 | 5 | | 二上達也 | 5 | | 永瀬拓矢 | 4 | | 桐山清澄 | 4 | | 内藤國雄 | 4 | | 深浦康市 | 3 | | 藤井猛 | 3 | | 佐藤天彦 | 3 | | 丸山忠久 | 3 | | 屋敷伸之 | 3 | | 広瀬章人 | 2 | | 福崎文吾 | 2 | | 中村修 | 2 | | 森雞二 | 2 | | 山田道美 | 2 | | 糸谷哲郎 | 1 | | 島朗 | 1 | | 有吉道夫 | 1 | | 森安秀光 | 1 | | 田中寅彦 | 1 | | 三浦弘行 | 1 | | 大内延介 | 1 | | 塚田泰明 | 1 | | 中村太地 | 1 | | 斎藤慎太郎 | 1 | | 菅井竜也 | 1 | | 木村一基 | 1 | | 髙見泰地 | 1 | +-----------------+-----+ 45 rows in set (0.00 sec)
重み付けによるスコア付け
大山先生や中原先生の時代にはタイトル戦が少なかったので、重み付けをしてみることにします。ここでは単純に、その年に存在していたタイトルの数で8を割った数値をスコアとしてカウントすることにします。3つしかタイトルがなかった年はひとつタイトルを獲ると 8/3=2.67 がスコアとなります(その年にタイトルが8個あったと仮定すると 2.67個を獲っていたことに相当するだろう、という単純化です)。なお、2022年のデータが3件しかないので、CASE式を使って強引に8件と見なす処理を加えています。
mysql> WITH tinyear as ( SELECT year, count(*) cnt FROM titleholder GROUP BY year ) -> SELECT kisi_name, SUM(score) * 8 score -> FROM ( -> SELECT h.year, h.kisi_name, y.cnt titlesInYear, -> CASE WHEN h.year=2022 then 1/8 -> ELSE 1/y.cnt END score -> FROM titleholder h -> LEFT OUTER JOIN tinyear y ON (h.year=y.year) -> ) t -> GROUP BY kisi_name -> ORDER BY score DESC -> LIMIT 30; +-----------------+----------+ | kisi_name | score | +-----------------+----------+ | 大山康晴 | 134.4104 | | 羽生善治 | 110.5992 | | 中原誠 | 75.1096 | | 木村義雄 | 54.6664 | | 渡辺明 | 33.8640 | | 谷川浩司 | 28.0024 | | 塚田正夫 | 26.6656 | | 米長邦雄 | 20.3360 | | 升田幸三 | 18.6648 | | 佐藤康光 | 14.7184 | | 森内俊之 | 13.7184 | | 加藤一二三 | 9.3832 | | 藤井聡太 | 9.0000 | | 久保利明 | 8.0024 | | 南芳一 | 7.0000 | | 郷田真隆 | 6.7160 | | 二上達也 | 6.3632 | | 豊島将之 | 6.0000 | | 内藤國雄 | 5.1440 | | 高橋道雄 | 5.0000 | | 桐山清澄 | 4.0000 | | 永瀬拓矢 | 4.0000 | | 藤井猛 | 3.4296 | | 深浦康市 | 3.4296 | | 丸山忠久 | 3.4296 | | 佐藤天彦 | 3.2864 | | 屋敷伸之 | 3.1432 | | 山田道美 | 2.6672 | | 森雞二 | 2.1432 | | 広瀬章人 | 2.1432 | +-----------------+----------+ 30 rows in set (0.01 sec)
大山先生、134点! 現在の8タイトル時代に大山先生が活躍していれば、134個のタイトルを獲得していた、ということに相当する数字です。すごい!
羽生先生もタイトルが7個の時代が多かったので、110点となりました。ソータ先生はもちろん9点のまま。
順位を数字で入れる
SQLでこんなこともできるよ、というデモンストレーションの意味しかありませんが、ウィンドウ関数を使用することで、順位を表す数字を結果に含めることができます。
同じスコアの人は同じ順位の数値となっているところがポイントです。
mysql> WITH tinyear as ( SELECT year, count(*) cnt FROM titleholder GROUP BY year ) -> SELECT RANK() OVER (ORDER BY SUM(score) DESC) rnk, -> kisi_name, SUM(score) * 8 score -> FROM ( -> SELECT h.year, h.kisi_name, y.cnt titlesInYear, -> CASE WHEN h.year=2022 then 1/8 -> ELSE 1/y.cnt END score -> FROM titleholder h -> LEFT OUTER JOIN tinyear y ON (h.year=y.year) -> ) t -> GROUP BY kisi_name -> ORDER BY score DESC -> LIMIT 30; +-----+-----------------+----------+ | rnk | kisi_name | score | +-----+-----------------+----------+ | 1 | 大山康晴 | 134.4104 | | 2 | 羽生善治 | 110.5992 | | 3 | 中原誠 | 75.1096 | | 4 | 木村義雄 | 54.6664 | | 5 | 渡辺明 | 33.8640 | | 6 | 谷川浩司 | 28.0024 | | 7 | 塚田正夫 | 26.6656 | | 8 | 米長邦雄 | 20.3360 | | 9 | 升田幸三 | 18.6648 | | 10 | 佐藤康光 | 14.7184 | | 11 | 森内俊之 | 13.7184 | | 12 | 加藤一二三 | 9.3832 | | 13 | 藤井聡太 | 9.0000 | | 14 | 久保利明 | 8.0024 | | 15 | 南芳一 | 7.0000 | | 16 | 郷田真隆 | 6.7160 | | 17 | 二上達也 | 6.3632 | | 18 | 豊島将之 | 6.0000 | | 19 | 内藤國雄 | 5.1440 | | 20 | 高橋道雄 | 5.0000 | | 21 | 桐山清澄 | 4.0000 | | 21 | 永瀬拓矢 | 4.0000 | | 23 | 丸山忠久 | 3.4296 | | 23 | 藤井猛 | 3.4296 | | 23 | 深浦康市 | 3.4296 | | 26 | 佐藤天彦 | 3.2864 | | 27 | 屋敷伸之 | 3.1432 | | 28 | 山田道美 | 2.6672 | | 29 | 森雞二 | 2.1432 | | 29 | 広瀬章人 | 2.1432 | +-----+-----------------+----------+ 30 rows in set (0.00 sec)
今回の計算ルールで一番得した人は?
今回、年間のタイトル戦開催回数に応じていわば「嵩上げ」をする計算式を採用しました。この計算方法で一番得した人はだれでしょうか。
じゃん!
取得結果の ratio列の値を見てください。 木村義雄先生 6.8倍、塚田正夫先生4.4倍、升田幸三先生2.67倍あたりが目立ちますね。
その他のカラムは、cnt 列が獲得期数、cnt_rnk列が獲得期数での順位 です。
mysql> WITH tinyear as ( SELECT year, count(*) cnt FROM titleholder GROUP BY year ) -> SELECT RANK() OVER (ORDER BY SUM(score) DESC) score_rnk, -> kisi_name, SUM(score) * 8 score, -> COUNT(*) cnt, -> RANK() OVER (ORDER BY COUNT(*) DESC) cnt_rnk, -> SUM(score) * 8/COUNT(*) ratio -> -> FROM ( -> SELECT h.year, h.kisi_name, y.cnt titlesInYear, -> CASE WHEN h.year=2022 then 1/8 -> ELSE 1/y.cnt END score -> FROM titleholder h -> LEFT OUTER JOIN tinyear y ON (h.year=y.year) -> ) t -> GROUP BY kisi_name -> ORDER BY score DESC -> LIMIT 30; +-----------+-----------------+----------+-----+---------+------------+ | score_rnk | kisi_name | score | cnt | cnt_rnk | ratio | +-----------+-----------------+----------+-----+---------+------------+ | 1 | 大山康晴 | 134.4104 | 80 | 2 | 1.68013000 | | 2 | 羽生善治 | 110.5992 | 99 | 1 | 1.11716364 | | 3 | 中原誠 | 75.1096 | 64 | 3 | 1.17358750 | | 4 | 木村義雄 | 54.6664 | 8 | 10 | 6.83330000 | | 5 | 渡辺明 | 33.8640 | 31 | 4 | 1.09238710 | | 6 | 谷川浩司 | 28.0024 | 27 | 5 | 1.03712593 | | 7 | 塚田正夫 | 26.6656 | 6 | 15 | 4.44426667 | | 8 | 米長邦雄 | 20.3360 | 19 | 6 | 1.07031579 | | 9 | 升田幸三 | 18.6648 | 7 | 12 | 2.66640000 | | 10 | 佐藤康光 | 14.7184 | 13 | 7 | 1.13218462 | | 11 | 森内俊之 | 13.7184 | 12 | 8 | 1.14320000 | | 12 | 加藤一二三 | 9.3832 | 8 | 10 | 1.17290000 | | 13 | 藤井聡太 | 9.0000 | 9 | 9 | 1.00000000 | | 14 | 久保利明 | 8.0024 | 7 | 12 | 1.14320000 | | 15 | 南芳一 | 7.0000 | 7 | 12 | 1.00000000 | | 16 | 郷田真隆 | 6.7160 | 6 | 15 | 1.11933333 | | 17 | 二上達也 | 6.3632 | 5 | 18 | 1.27264000 | | 18 | 豊島将之 | 6.0000 | 6 | 15 | 1.00000000 | | 19 | 内藤國雄 | 5.1440 | 4 | 20 | 1.28600000 | | 20 | 高橋道雄 | 5.0000 | 5 | 18 | 1.00000000 | | 21 | 桐山清澄 | 4.0000 | 4 | 20 | 1.00000000 | | 21 | 永瀬拓矢 | 4.0000 | 4 | 20 | 1.00000000 | | 23 | 丸山忠久 | 3.4296 | 3 | 23 | 1.14320000 | | 23 | 藤井猛 | 3.4296 | 3 | 23 | 1.14320000 | | 23 | 深浦康市 | 3.4296 | 3 | 23 | 1.14320000 | | 26 | 佐藤天彦 | 3.2864 | 3 | 23 | 1.09546667 | | 27 | 屋敷伸之 | 3.1432 | 3 | 23 | 1.04773333 | | 28 | 山田道美 | 2.6672 | 2 | 28 | 1.33360000 | | 29 | 森雞二 | 2.1432 | 2 | 28 | 1.07160000 | | 29 | 広瀬章人 | 2.1432 | 2 | 28 | 1.07160000 | +-----------+-----------------+----------+-----+---------+------------+ 30 rows in set (0.00 sec)
まとめ
今回の計算ルールで重み付けをした場合でも、羽生先生の 99期というのは大山先生以外には抜かれない大記録であることがわかりました。
データさえあれば、SQLってこのように楽しむこともできるので、ぜひ(これからの方は)学んで、楽しんでいただけたらと思います。ちょっとしたSQLデモでした。
.
.
追記(2022/07/21 14:30) 年ごとの実施タイトル戦リスト
どの年に何のタイトルがあったのかを知りたいとの声をいただいたので、GROUP_CONCAT()関数を使って出力してみました。
mysql> SELECT year, GROUP_CONCAT(DISTINCT title_name) FROM titleholder GROUP BY year; +------+---------------------------------------------------------------------------------+ | year | GROUP_CONCAT(DISTINCT title_name) | +------+---------------------------------------------------------------------------------+ | 1937 | 名人戦 | | 1940 | 名人戦 | | 1942 | 名人戦 | | 1944 | 名人戦 | | 1945 | 名人戦 | | 1947 | 名人戦 | | 1948 | 名人戦 | | 1949 | 名人戦 | | 1950 | 九段戦,名人戦 | | 1951 | 九段戦,名人戦,王将戦 | | 1952 | 九段戦,名人戦,王将戦 | | 1953 | 九段戦,名人戦,王将戦 | | 1954 | 九段戦,名人戦,王将戦 | | 1955 | 九段戦,名人戦,王将戦 | | 1956 | 九段戦,名人戦,王将戦 | | 1957 | 九段戦,名人戦,王将戦 | | 1958 | 九段戦,名人戦,王将戦 | | 1959 | 九段戦,名人戦,王将戦 | | 1960 | 九段戦,名人戦,王位戦,王将戦 | | 1961 | 九段戦,名人戦,王位戦,王将戦 | | 1962 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1963 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1964 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1965 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1966 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1967 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1968 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1969 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1970 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1971 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1972 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1973 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1974 | 十段戦,名人戦,棋聖戦,王位戦,王将戦 | | 1975 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1976 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1977 | 十段戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1978 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1979 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1980 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1981 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1982 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦 | | 1983 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦 | | 1984 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦 | | 1985 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦 | | 1986 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦 | | 1987 | 十段戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦 | | 1988 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1989 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1990 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1991 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1992 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1993 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1994 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1995 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1996 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1997 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1998 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 1999 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2000 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2001 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2002 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2003 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2004 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2005 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2006 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2007 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2008 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2009 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2010 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2011 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2012 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2013 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2014 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2015 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2016 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2017 | 名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2018 | 叡王戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2019 | 叡王戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2020 | 叡王戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2021 | 叡王戦,名人戦,棋王戦,棋聖戦,王位戦,王将戦,王座戦,竜王戦 | | 2022 | 叡王戦,名人戦,棋聖戦 | +------+---------------------------------------------------------------------------------+ 81 rows in set (0.00 sec)
.
なお、今回はタイトル戦に関する情報は名称しか持っていないので、並び替えることにあまり意味はありませんが、このように ORDER BY を指定することもできます。
SELECT year, GROUP_CONCAT(DISTINCT title_name ORDER BY title_name DESC) FROM titleholder GROUP BY year;
結果(部分):
| 2015 | 竜王戦,王座戦,王将戦,王位戦,棋聖戦,棋王戦,名人戦 | | 2016 | 竜王戦,王座戦,王将戦,王位戦,棋聖戦,棋王戦,名人戦 | | 2017 | 竜王戦,王座戦,王将戦,王位戦,棋聖戦,棋王戦,名人戦 | | 2018 | 竜王戦,王座戦,王将戦,王位戦,棋聖戦,棋王戦,名人戦,叡王戦 | | 2019 | 竜王戦,王座戦,王将戦,王位戦,棋聖戦,棋王戦,名人戦,叡王戦 |