SQLServerにおけるJSONドキュメント型データのクエリ問題を解決する。
最近、あるプロジェクトで問題に遭遇しました。JSON形式で保存されたデータをレポート内でカウントするには?
例えば、各質問の回答を記録するアンケート記録テーブルがあります。構造は下図のようになっています(横型のテーブルデザイン)。
Q1_Answer]、[Q2_Answer]、[Q3_Answer]に記録されているデータは、選択肢の値であることからJSON文書の形式になっており、複数の選択肢があることを考慮して、以下の形式で格納されます。
1 [
{"code":"a", "desc":"Jan."},
{"code":"b", "desc":"Feb."}
]
ここで、codeはオプションを表し、descはオプションのテキスト説明を表します。
さて、ユーザーはPowerBIを使って、結果の統計を実施したいと考えています。いくつかの質問があります。
- Power BI では、JSON データからオプション値を直接読み取ることができない
-
また、複数選択である場合の対処法。
分析に適したデータ構造は、次のようなものです。
上記のQ2ユーザーは、2つの選択肢を記入したことに注意してください。アンケート自体は複数の選択肢をサポートするように設定されています。データの保存にはJSON文書構造が使用されており、主に収集とデータアクセスを容易にするために使用されています。そのため、収集したデータを簡単にカウントできるようにするために、いくつかの追加のデータ処理があります。
いろいろ調べた結果、UNPIVOTメソッドとOPENJSONメソッドを組み合わせて使うことで、期待通りの効果が得られることがわかりました。その手順は以下の通りです。
フォームの準備とデータの初期化
-- 1 create table
Create Table T_Questionaire(id int identity(1,1) primary key, username varchar(100), t1 nvarchar(500),t2 nvarchar(500),t3 nvarchar(500), dt datetime)
-- 2 init data
Insert into T_Questionaire( username, t1, t2, t3, dt)
values ('John' , '[{"code":"a", "desc":"Monday"}]', '[{"code":"a", " desc":"Jan."}]', '[{"code":"b", "desc":"2021"}]' ,getdate())
, ('Alice' , '[{"code":"b", "desc":"Tuesday"}]', '[{"code":"a", "desc& quot;:"Jan."}, {"code":"b", "desc":"Feb."}]', '[{"code":"a", "desc"', '[{"code":"a", " "desc":"2020"},{"code":"b", "desc":"2021"}]' ,getdate())
データの内容です。
変換されたビューを作成する。
Create or alter view V_VerticalQuestionaire
as
with pt as (
select a.username, a.T, a.answers, a.dt from dbo.
unpivot
( answers for T in (t1,t2,t3 ))
a)
select pt.username, pt.dt, pt.T , aw.code, aw.[desc]
from pt
cross apply openjson(answers) WITH (code NVARCHAR(100) '$.code', [desc] NVARCHAR(100) '$.desc') aw
クエリーの結果は以下の通りです。
解決策の考え方をまとめると
1 列行をunpivotで変換して、横型の表レコードが縦型の表レコードになるようにするところから始める
2 openjsonでjsonデータをコレクションデータに変換し、cross applyでコレクションを展開する。
今回の記事は、SQLServerでJSONドキュメントベースのデータをクエリするためのものです。SQLServerでのJSONデータのクエリについては、スクリプトハウスの過去記事を検索するか、以下の記事を引き続き閲覧してください。
関連
-
SQLインジェクションとその防止、マイベイトの基本的な役割について
-
SQL Server2017では、IPをサーバー名としてサーバーに接続します。
-
DataGrip Formatting SQLの実装(カスタムSqlフォーマット)
-
SQL文におけるJOINの利用シーンの分析
-
日付で年齢を判定するSQLサンプルコード 関数
-
SQL Serverでの判定文(IF ELSE/CASE WHEN)の使用例
-
SQL Server のジョブが失敗しました。所有者がサーバーアクセス権を持っているかどうか判断できない
-
SQLServerのエラーです。15404, unable to get information about Windows NT group/user WIN-8IVSNAQS8T7Administrator
-
SQL クエリ結果カラムのカンマ区切り文字列へのステッチング法
-
そのPHP環境の普遍的なパスワードのSQLインジェクションの脆弱性と防御手段
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン