2021年6月3日木曜日

ワクチン接種状況ダッシュボードに機能を追加する

前回作成してみたワクチン接種状況ダッシュボードですが、同じものを作るだけであれば、あまり意味がありません。せっかく手元にデータを持ってきたのですから、少々活用してみました。


ワクチン接種数の7日間移動平均をグラフに追加する

接種数日次推移のグラフに7日間の接種数の移動平均を表示させてみます。

リージョンの接種数日次推移を選択し、Attributesのチャートのタイプを棒から組合せに変更します。移動平均は棒ではなく、折れ線で表示させます。


シリーズの作成を行います。名前を2回目 - (7日間移動平均)とします。タイプは折れ線を選択します。ソースのタイプはSQL問合せ、SQL問合せとして以下を記述します。

select
count_date,
avg(count) over (order by count_date asc
range between interval '6' day preceding and current row
) count
from (
select
count_date,
sum(count) count
from covid19_vaccination_results
where status = 2
and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
and age in (select column_value from apex_string.split(:P1_AGE, ':'))
and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
group by count_date
)

元々の接種数の検索結果にSQLのWINDOW関数を適用することで、移動平均を算出しています。

SQLのWINDOW関数の結果をすぐにチャートに表示できるのは便利、と感じるか、SQLで書かなければいけないのか?と感じるかで、Oracle APEXが使えるツールと感じるかどうかの分かれ目になると思います。SQL自体はOracle APEXを使うかどうか、さらにはOracle Databaseを使うかどうかにも関係なく役立てることができる知識なので、難しくても学ぶ価値があります。

送信するページ・アイテムとしてP1_GENDER、P1_AGE、P1_PREFECTUREを指定します。

列のマッピングとして、ラベルにCOUNT_DATE、値にCOUNTを指定します。外観の積上げカテゴリに移動平均2を入力します。移動平均は積み上げ対象から外したいので、単独となる積上げカテゴリにしています。


作成したシリーズ2回目 - (7日間移動平均)を重複させます。名前は1回目 - (7日間移動平均)に変更します。SQL問合せを以下に変更します。where status = 2の部分をwhere status = 1に変更しています。

select
count_date,
avg(count) over (order by count_date asc
range between interval '6' day preceding and current row
) count
from (
select
count_date,
sum(count) count
from covid19_vaccination_results
where status = 1
and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
and age in (select column_value from apex_string.split(:P1_AGE, ':'))
and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
group by count_date
)

積上げカテゴリは移動平均1に変更します。

元々あったシリーズ1回目と2回目を選択し、積上げカテゴリを接種数とします。日次の接種数は積み上げの対象になります。

ページの保存と実行を行うと、接種数日次推移のチャートに、7日間の移動平均を表す折れ線グラフが追加されていることが確認できます。


カラムの値に依存してセルの背景色を変更する

元のダッシュボードは接種率に応じて連続的に背景色を変更しています。Oracle APEXで、それを簡単に実装する方法は見つけることはできませんでした。

その代わりに、段階的に背景色を変更してみます。それぞれの背景色を設定するCSSクラスを定義します。これはページのプロパティのCSS、インラインに記載します。CSSクラスは全部で11あります。

.bgdolor-level-100 {
background-color: rgb(0,255,255);
}
.bgcolor-level-90 {
background-color: rgb(25,255,255);
}
.bgcolor-level-80 {
background-color: rgb(50,255,255);
}
.bgcolor-level-70 {
background-color: rgb(75,255,255);
}
.bgcolor-level-60 {
background-color: rgb(100,255,255);
}
.bgcolor-level-50 {
background-color: rgb(125, 185, 185);
}
.bgcolor-level-40 {
background-color: rgb(150,255,255);
}
.bgcolor-level-30 {
background-color: rgb(175,255,255);
}
.bgcolor-level-20 {
background-color: rgb(200,255,255);
}
.bgcolor-level-10 {
background-color: rgb(225,255,255);
}
.bgcolor-level-00 {
background-color: rgb(255,255,255);
}


対話グリッドのリージョン都道府県別接種数 - 接種率を選択し、SQL問合せを以下に変更します。検索結果の列としてCOLORを追加し、接種率が0, 10, 20, ... 100までの11段階に分けてCSSクラスを返すようにします。

with v_first as (
select
prefecture,
sum(count) count
from covid19_vaccination_results
where status = 1
and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
and age in (select column_value from apex_string.split(:P1_AGE, ':'))
and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
group by prefecture
),
v_second as (
select
prefecture,
sum(count) count
from covid19_vaccination_results
where status = 2
and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
and age in (select column_value from apex_string.split(:P1_AGE, ':'))
and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
group by prefecture
),
v_total as (
select
prefecture,
prefecture_name,
sum(count) total
from covid19_vaccination_targets
where 1=1
and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
and age in (select column_value from apex_string.split(:P1_AGE, ':'))
and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
group by prefecture, prefecture_name
)
select
f.prefecture prefecture,
t.prefecture_name prefecture_name,
t.total population,
(f.count + s.count) count_total,
f.count count_first,
(f.count / t.total) * 100 rate_first,
s.count count_second,
(s.count / t.total) * 100 rate_second,
case
when (f.count / t.total) * 100 >= 100 then
'bgcolor-level-100'
when (f.count / t.total) * 100 >= 90 then
'bgcolor-level-90'
when (f.count / t.total) * 100 >= 80 then
'bgcolor-level-80'
when (f.count / t.total) * 100 >= 70 then
'bgcolor-level-70'
when (f.count / t.total) * 100 >= 60 then
'bgcolor-level-60'
when (f.count / t.total) * 100 >= 50 then
'bgcolor-level-50'
when (f.count / t.total) * 100 >= 40 then
'bgcolor-level-40'
when (f.count / t.total) * 100 >= 30 then
'bgcolor-level-30'
when (f.count / t.total) * 100 >= 20 then
'bgcolor-level-20'
when (f.count / t.total) * 100 >= 10 then
'bgcolor-level-10'
else
'bgcolor-level-00'
end color
from v_first f
join v_second s on f.prefecture = s.prefecture
join v_total t on f.prefecture = t.prefecture

列COLORが対話グリッドに認識されるので、この列のタイプを非表示に変更します。


列COLORとして返される値を、列RATE_FIRSTにCSSクラスとして適用します。

列RATE_FIRSTを選択し、詳細のJavaScript初期化コードとして以下を記述します。

function(options){
options.defaultGridColumnOptions = {
cellCssClassesColumn: 'COLOR'
};
return options;
}

対話グリッドの列のプロパティcellCssClassesColumnとしてCOLORを設定しています。これで列COLORの値が、CSSクラスとして列RATE_FIRSTに適用されます。


ページの保存と実行を行うと、1回目接種率のセルの色が異なって表示される都道府県があることが確認できます。



都道府県の概要を表示する


都道府県の選択時に全国の概要ではなく、都道府県の概要を代わりに表示させます。

リージョン全国 - 概要を重複させ、名前を都道府県概要に変更します。ソースのSQL問合せ、送信するページ・アイテムはリージョン都道府県別接種数 - 接種率よりコピーします。


追加でレポートに認識された列PREFECTURE、PREFECTURE_NAME、COLORのタイプを非表示列にします。


追加したリージョン都道府県概要が、検索条件の変更時にリフレッシュされるようTrueアクションの作成をします。

ページ・アイテムP1_GENDER、P1_AGE、P1_PREFECTUREそれぞれに、アクションがリフレッシュのTrueアクションを作成します。影響を受ける要素の選択タイプとしてリージョン、リージョンとして都道府県概要を指定します。


全国が表示対象のときは全国 - 概要のリージョンだけを表示し、都道府県が選択されているときは都道府県概要のリージョンだけを表示するように設定します。

全国ボタンをクリックしたときに実行される動的アクション都道府県を全選択にTrueアクションを3つ追加します。

アクションは表示、リージョンは全国 - 概要、初期化時に実行はON。
アクションは表示、リージョンは都道府県別接種数 - 接種率、初期化時に実行はON。
アクションは非表示、リージョンは都道府県概要、初期化時に実行はON。


次に対話グリッドで都道府県の選択を行ったときに実行される動的アクションを追加します。

最初に、動的アクション都道府県選択のクライアント側の条件のタイプをJavaScript式として、以下のJavaScript式を設定します。

this.data.selectedRecords.length > 0


TrueアクションのJavaScriptコードの実行から、クライアント側の条件を外します。動的アクション自体にクライアント側の条件がついているので、Trueアクションには不要になりました。


全国のボタンをクリックしたときとは反対に、都道府県概要のリージョンだけが表示されるよう、Trueアクションを3つ作成します。

アクションは表示、リージョンは都道府県概要、初期化時に実行はOFF。
アクションは非表示、リージョンは全国 - 概要、初期化時に実行はOFF。
アクションは非表示、リージョンは都道府県別接種数 - 接種率、初期化時に実行はOFF。


この状態でページを実行してみます。全国の表示は以下のようになります。


都道府県を選択すると、以下のようになります。


レイアウトが崩れない様に、リージョンを追加し、全国 - 概要と都道府県概要のリージョンを作成したリージョンのサブ・リージョンにします。

リージョンの作成を行い、Content Bodyの先頭に配置します。識別のタイトルを概要レイアウトとし、タイプに静的コンテンツを選択します。外観のテンプレートとしてBlank with Attributesを選択します。


リージョン全国 - 概要および都道府県概要のレイアウトの親リージョンを概要レイアウトに変更します。


以上で全国と都道府県で選択を切り替えても、ページのレイアウトが保持されます。


都道府県概要のタイトル表示を都道府県名にする


都道府県を選択したときのレポートのタイトルが都道府県概要となっており、どの都道府県かわかりません。ここに都道府県名を表示させます。

都道府県概要のリージョンに静的IDを設定します。静的IDはpref_specificとします。


都道府県選択を行なったときに実行されるTrueアクションである、JavaScriptコードの実行のコードを以下に変更します。末尾に1行追記しリージョンのタイトルに都道府県名を設定しています。

let model = this.data.model;
let record = this.data.selectedRecords[0];
let prefcode = model.getValue(record, "PREFCODE");
$s("P1_PREFECTURE", prefcode);
document.getElementById("pref_specific_heading").textContent
= model.getValue(record, "PREFECTURE_NAME");

idがpref_sepecific_headingであるHTML要素のテキスト部分に、都道府県名を代入しています。


今回の作業は以上になります。今まので作業は、公開済みのアプリケーションのエクスポートに含まれています。

作成したアプリケーションは以下よりアクセスできます。

Oracle APEXのアプリケーションの作成の参考になれば幸いです。

完

2021年6月2日水曜日

ワクチン接種状況ダッシュボードをOracle APEXで作ってみる

 政府CIOポータルより公表されている、ワクチン接種状況ダッシュボードをOracle APEXを使って作ってみました。元のサイトはTabuleauで作っているようです。

ダッシュボードで使用しているデータは、すべてオープンデータとして公開されています。これらのデータの取り込み方法は、以前に記事を書いています。

改行で区切ったJSON(Newline Delimited JSON)のデータをロードする
ワクチン接種数のデータです。表COVID19_VACCINATION_RESULTSにデータをロードしています。公開されているデータの取り込みに表COVID19_DATA_FILESを作成していますが、ダッシュボードの作成には使用していません。

総務省が公表している【総計】令和2年1月1日住民基本台帳年齢階級別人口(市区町村別)のExcelファイルを読み込む
ワクチン接種対象となる人口のデータです。表EGOV_POPULATIONにデータをロードしています。

作成するページは1ページのみです。

以下より、アプリケーションの作り方を紹介します。

最初にワクチン接種の対象となる人数を、都道府県別(PREFECTURE)、男女別(GENDER)、年代(AGE)毎に集計したビューCOVID19_VACCINATION_TARGETSを作成します。以下のDDLを実行します。集計結果はCOUNTになります。

CREATE OR REPLACE FORCE VIEW "COVID19_VACCINATION_TARGETS"
("PREFECTURE", "PREFECTURE_NAME", "GENDER", "AGE", "COUNT") AS
select
trunc(municipality_code/10000) prefecture,
prefecture_name,
gender,
'-64' age,
(age00+age05+age10+age15+age20+age25+age30+age35+age40+age45+age50+age55+age60) count
from egov_population
where city_name is null and gender = 'M' and municipality_code is not null
union all
select
trunc(municipality_code/10000) prefecture,
prefecture_name,
gender,
'65-' age,
(age65+age70+age75+age80+age85+age90+age95+age100) count
from egov_population
where city_name is null and gender = 'M' and municipality_code is not null
union all
select
trunc(municipality_code/10000) prefecture,
prefecture_name,
gender,
'-64' age,
(age00+age05+age10+age15+age20+age25+age30+age35+age40+age45+age50+age55+age60) count
from egov_population
where city_name is null and gender = 'F' and municipality_code is not null
union all
select
trunc(municipality_code/10000) prefecture,
prefecture_name,
gender,
'65-' age,
(age65+age70+age75+age80+age85+age90+age95+age100) count
from egov_population
where city_name is null and gender = 'F' and municipality_code is not null
/


PREFECTUREは1から47、GENDERはMとF、AGEは-64と65-の値をそれぞれ持ちます。これらの値はNDJSON形式で提供されているワクチン接種のデータに合わせています。

ホーム・ページのみの空のアプリケーションを作成します。アプリケーション作成ウィザードを起動し、名前をワクチン接種状況ダッシュボードとします。アプリケーションの作成を実行します。


アプリケーションが作成されます。編集するページは1 - ホームのみです。


ページ・デザイナでホーム・ページを開き、全国の概要を表示するレポートを作成します。リージョンの作成を行い、タイトルを全国 - 概要とします。タイプにクラシック・レポートを選択します。ソースのタイプをSQL問合せとし、以下のSELECT文を記述します。

with v_first as (
select
sum(count) count
from covid19_vaccination_results
where status = 1
),
v_second as (
select
sum(count) count
from covid19_vaccination_results
where status = 2
),
v_total as (
select
sum(count) total
from covid19_vaccination_targets
)
select
t.total population,
f.count + s.count count_total,
f.count count_first,
(f.count / t.total) * 100 rate_first,
s.count count_second,
(s.count / t.total) * 100 rate_second
from v_first f, v_second s, v_total t

1回目の全接種回数はビューv_firstで集計、2回目はv_second、対象者はv_totalで集計しています。人口、接種数と接種率をSELECT文の結果として返しています。


政府のダッシュボードでは、都道府県を選択すると、その選択が表示に反映されます。都道府県ごとの表示は別に実装するので、このレポートではつねに全国の情報を表示しています。

レポートに表示される列の設定を行います。列を選択し、それぞれ見栄えの調整を行います。


列POPULATIONには、以下を設定します。
  • 識別
    • タイプ:プレーン・テキスト
  • ヘッダー
    • ヘッダー:人口
    • 位置合わせ:中央
  • レイアウト
    • 列の位置合せ:右
  • 外観
    • 書式マスク:999G999G999G999G990
  • ソート
    • ソート可能:OFF
列COUNT_TOTALは、ヘッダーを接種数とします。それ以外は列POPULATIONと同じです。
  • ヘッダー
    • ヘッダー:接種数
列COUNT_FIRSTは、ヘッダーを1回目接種数とします。それ以外は列POPULATIONと同じです。
  • ヘッダー
    • ヘッダー:1回目接種数
列RATE_FIRSTは、ヘッダーを1回目接種率とします。今までと設定は大体同じですが、書式マスクの指定に小数点2桁を含め、HTML式を使って数値の末尾に%を付けています。
  • ヘッダー
    • ヘッダー:1回目接種率
  • 外観
    • 書式マスク:999G999G999G999G990D00
  • 列の書式
    • HTML式:#RATE_FIRST#%
列COUNT_SECONDは、ヘッダーを2回目接種数とします。それ以外は列COUNT_FIRSTと同じです。
  • ヘッダー
    • ヘッダー:2回目接種数
列RATE_SECONDは、ヘッダーを2回目接種率とします。それ以外は列RATE_FIRSTと同じです。
  • ヘッダー
    • ヘッダー:2回目接種率
  • 列の書式
    • HTML式:#RATE_SECOND#%
クラシック・レポートの表示を調整します。Attributesの外観のテンプレート・オプションを開きます。


Stretch Reportにチェックを入れます。また、詳細のPagination DisplayはHide when all rows displayedに設定します。結果は1行なのでページネーションの表示は不要です。


ページの保存と実行を行い、今まで作成した内容を確認します。


ダッシュボードを表示する条件を作成します。リージョンの作成を行い、名前を条件、タイプを静的コンテンツとします。レイアウトの新規行の開始はOFFにします。


作成したリージョンで、ページ・アイテムの作成を行います。


性別を選択するページ・アイテムには、以下の設定を行います。
  • 識別
    • 名前:P1_GENDER
    • タイプ:ラジオ・グループ
  • ラベル
    • ラベル:性別
  • 設定
    • 列の数:3
    • 選択時のページ・アクション:None
  • LOV
    • タイプ:静的値
    • 静的値
      • 男:M
      • 女:F
      • すべて:M:F:U
      • 実行時にソート:OFF
    • 追加値の表示:OFF
    • NULL値の表示:OFF
  • デフォルト
    • タイプ:静的
    • 静的値:M:F:U
年代を選択するページ・アイテムを作成し、以下の設定を行います。
  • 識別
    • 名前:P1_AGE
    • タイプ:ラジオ・グループ
  • ラベル
    • ラベル:年代
  • 設定
    • 列の数:2
    • 選択時のページ・アクション:None
  • レイアウト
    • 新規行の開始:OFF
  • LOV
    • タイプ:静的値
      • 65歳以上:65-
      • すべて:-64:65-:UNK
      • 実行時にソート:OFF
    • 追加値の表示:OFF
    • NULL値の表示:OFF
  • デフォルト
    • タイプ:静的
    • 静的値:-64:65-:UNK
都道府県を選択するページ・アイテムを作成し、以下の設定を行います。都道府県の選択は対話グリッドから行うため、このページ・アイテムは非表示とします。
  • 識別
    • 名前:P1_PREFECTURE
    • タイプ:非表示
  • デフォルト
    • タイプ:静的
    • 静的値:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:26:27:28:29:30:31:32:33:34:35:36:37:38:39:40:41:42:43:44:45:46:47
都道府県の選択をリセットし、すべての都道府県を対象にするボタンの作成を行います。
    • 識別
      • ボタン名:B_ALL
      • ラベル:全国
    • レイアウト
      • ボタン位置:Region Body
      • 新規行の開始:OFF (場所はP1_PREFECTUREの右隣に配置します)
    • 動作
      • アクション:動的アクションで定義
    ボタンB_ALLに動的アクションの作成を行います。

    • 識別
      • 名前:都道府県を全選択
    • タイミング
      • イベント:クリック
      • 選択タイプ:ボタン
      • ボタン:B_ALL
    Trueアクションの設定を行います。

    • 識別
      • アクション:値の設定
    • 設定
      • タイプの設定:Static Assignment
      • 値:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:18:19:20:21:22:23:24:25:26:27:28:29:30:31:32:33:34:35:36:37:38:39:40:41:42:43:44:45:46:47
      • 変更イベントの禁止:OFF
    • 影響を受ける要素
      • 選択タイプ:アイテム
      • アイテム:P1_PREFECTURE
    ページの保存と実行を行い、今まで作成した内容を確認します。


    接種数日次推移のチャートの作成を行います。リージョンの作成を実行します。

    • 識別
      • タイトル:接種数日次推移
      • タイプ:チャート
    Attributesタブを開き、チャートの属性を設定します。

    • チャート
      • タイプ:棒
    • 外観
      • 向き:縦
      • 積上げ:ON
    • 設定
      • 時間軸タイプ:有効
    • 凡例
      • 表示:ON
      • 位置:下
    シリーズとして、最初に2回目の接種数を作成します。(デフォルトでシリーズは1つ作成されているので、正しくは作成済みのシリーズの変更です)。


    接種数を集計するSQLは以下になります。

    select
    count_date,
    sum(count) count
    from covid19_vaccination_results
    where status = 2
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by count_date
    • 識別
      • 名前:2回目
    • ソース
      • 位置:ローカル・データベース
      • タイプ:SQL問合せ
      • SQL問合せ:上記
      • 送信するアイテム:P1_GENDER,P1_AGE,P1_PREFECTURE
    • 列のマッピング
      • ラベル:COUNT_DATE
      • 値:COUNT
    シリーズ2回目を重複させ、1回目を作成します。識別の名前を1回目に変更し、SQLのwhere status = 2の部分をwhere status = 1に書き換えます。

    select
    count_date,
    sum(count) count
    from covid19_vaccination_results
    where status = 1
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by count_date

    y軸の値の書式を少数、小数点を0、書式スケールは自動にします。


    ページの保存と実行を行い、今まで作成した内容を確認します。


    接種率日次推移のチャートの作成を行います。作成済みの接種数日次推移のチャート・リージョンを重複させます。識別の名前を接種率日次推移に変更します。チャートを横並びにするため、レイアウトの新規行の開始をOFFにします。


    チャートのタイプは折れ線に変更します。外観の積上げはOFFにします。


    2回目のシリーズのSQL問合せを以下に変更します。

    select
    count_date,
    (
    sum(count)
    over (order by count_date asc)
    /
    (
    select sum(count) total
    from covid19_vaccination_targets
    where 1=1
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    )
    )
    rate
    from
    (
    select
    count_date,
    sum(count) count
    from covid19_vaccination_results
    where status = 2
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by count_date
    )

    列のマッピングの値はRATEに変更します。


    1回目のシリーズも変更します。SQL問合せはwhere status = 2の部分をstatus = 1に変更しています。列のマッピングの値はRATEに変更します。

    select
    count_date,
    (
    sum(count)
    over (order by count_date asc)
    /
    (
    select sum(count) total
    from covid19_vaccination_targets
    where 1=1
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    )
    )
    rate
    from
    (
    select
    count_date,
    sum(count) count
    from covid19_vaccination_results
    where status = 1
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by count_date
    )


    y軸の値の書式を割合、小数点を2にします。


    ページの保存と実行を行い、今まで作成した内容を確認します。


    都道府県ごとの接種数、接種率を一覧する対話グリッドの作成を行います。リージョンの作成を行います。識別のタイトルは都道府県別接種数 - 接種率、タイプに対話グリッドを選択します。ソースのタイプはSQL問合せで、SQL問合せには以下を記述します。

    with v_first as (
    select
    prefecture,
    sum(count) count
    from covid19_vaccination_results
    where status = 1
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by prefecture
    ),
    v_second as (
    select
    prefecture,
    sum(count) count
    from covid19_vaccination_results
    where status = 2
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by prefecture
    ),
    v_total as (
    select
    prefecture,
    prefecture_name,
    sum(count) total
    from covid19_vaccination_targets
    where 1=1
    and gender in (select column_value from apex_string.split(:P1_GENDER, ':'))
    and age in (select column_value from apex_string.split(:P1_AGE, ':'))
    and prefecture in (select column_value from apex_string.split(:P1_PREFECTURE, ':'))
    group by prefecture, prefecture_name
    )
    select
    f.prefecture prefecture,
    t.prefecture_name prefecture_name,
    t.total population,
    (f.count + s.count) count_total,
    f.count count_first,
    (f.count / t.total) * 100 rate_first,
    s.count count_second,
    (s.count / t.total) * 100 rate_second
    from v_first f
    join v_second s on f.prefecture = s.prefecture
    join v_total t on f.prefecture = t.prefecture

    送信するページ・アイテムとして、P1_GENDER,P1_AGE,P1_PREFECTUREを指定します。


    列をそれぞれ選択し、設定を行います。列PREFECTUREのヘッダーは#、列PREFECTURE_NAMEのヘッダーは都道府県とします。それ以外は全国 - 概要のレポートと同じヘッダー、位置合せ、列の位置合せ、書式マスクの設定を適用します。タイプはすべて、数値フィールドのまま変更しません。


    対話グリッドのHTML式はクラシック・レポートとは異なるため、接種率に%をつけるためには使用できません。代わりにCSSを使います。

    ページに、インラインで以下のCSSクラスappendPercentSignを定義します。ページのプロパティのCSS、インラインに記載します。

    .appendPercentSign::after {
    content: "%";
    }
        

    列RATE_FIRSTとRATE_SECONDの外観のCSSクラスにappendPercentSignを指定します。


    ページの保存と実行を行い、今まで作成した内容を確認します。


    チャートとレポートは、すべて作成されました。

    これから条件の変更がチャートやレポートに反映されるよう、動的アクションを追加します。

    最初に対話グリッド上で都道府県を選択可能にします。対話グリッドで動的アクションの作成を行います。

    識別の名前を都道府県選択とします。タイミングのイベントは選択の変更[対話グリッド]、選択タイプはリージョン、リージョンは都道府県別接種数 - 接種率です。


    Trueアクションを選択し、アクションとしてJavaScriptコードの実行を選びます。設定のコードには以下を記述します。対話グリッドの行をクリックして選択された都道府県のコードが、ページ・アイテムP1_PREFECTUREに設定されます。

    let model = this.data.model;
    let record = this.data.selectedRecords[0];
    let prefecture = model.getValue(record, "PREFCTURE");
    $s("P1_PREFECTURE", prefecture);

    選択された行が存在するときのみ実行されるよう、クライアント側の条件としてタイプにJavaScript式を選び、以下のJavaScript式を設定します。

    this.data.selectedRecords.length > 0

    アクションのクライアント側の条件は、Oracle APEX 21.1の新機能です。


    ページ・アイテムP1_GENDER、P1_AGE、P1_PREFECTUREが変更されたときに、2つのチャートと1つの対話グリッドがリフレッシュされるよう、動的アクションの作成をします。

    タイミングのイベントは変更、選択タイプはアイテムです。アイテムには、ぞれぞれのページ・アイテムを指定します。


    Trueアクションの識別のアクションはリフレッシュです。影響を受ける要素はリージョンで、リージョンには接種数日次推移、接種率日次推移、都道府県別接種数 - 接種率の3つリージョンをそれぞれ別のTrueアクションとして作成します。3つのページ・アイテムすべてにTrueアクションを3つずつ作成します。


    以上でアプリケーションの完成です。作成したアプリケーションは以下の様な動作になります。


    見栄えなどはまだまだ調整の余地はありますが、基本的な機能は実装できていると思います。

    作成したアプリケーションのエクスポートを以下に置きました。
    https://github.com/ujnak/apexapps/blob/master/exports/vaccine-dashboard.sql

    Oracle APEXのアプリケーション作成の参考になれば幸いです。

    完