一个SQLServer中JSON文档型数据的查询问题
近日在项目中遇到一个问题: 如何在报表中统计JSON格式存储的数据?
例如有个调查问卷记录表,记录每个问题的答案。 其结构示意如下(横表设计)
| Id | user | date | Q1_Answer | Q2_Answer | Q3_Answer | 
| 行Id | 答题用户 | 答题日期 | 问题一结果 | 问题二结果 | 问题三结果 | 
在[Q1_Answer]、[Q2_Answer]、[Q3_Answer]中记录的数据格式是JSON文档内容,因为是选项值,而且考虑到可能有多选, 所以存储的格式如下:
1 [
{"code":"a", "desc":"Jan."},
{"code":"b", "desc":"Feb."}
]
其中 code 表示选项, desc 表示选项的文字描述。
现在,用户想用PowerBI 来实现对结果的统计。有如下几个问题:
- 在Power BI中,无法直接从JSON数据中读取到选项值
 - 如果是多选,又该如何处理。
 
比较适合分析的数据结构应该长这样:
| 行Id | 答题用户 | 答题日期 | 问题编号 | 用户选项 | 选项文字 | 
| 1 | user1 | 2021-6-26 | Q1 | A | Jan. | 
| 2 | user1 | 2021-6-26 | Q2 | A | Mon. | 
| 3 | user1 | 2021-6-26 | Q2 | B | Tue. | 
| 4 | user1 | 2021-6-26 | Q3 | A | Swimming | 
| 6 | user2 | 2021-6-26 | Q1 | B | Feb. | 
| 7 | user2 | 2021-6-26 | Q2 | ... | ... | 
注意,上述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":"Jan."}, {"code":"b", "desc":"Feb."}]', '[{"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.T_Questionaire a
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文档型数据的查询问题的更多相关文章
- 最近学习工作流 推荐一个activiti 的教程文档
		
全文地址:http://www.mossle.com/docs/activiti/ Activiti 5.15 用户手册 Table of Contents 1. 简介 协议 下载 源码 必要的软件 ...
 - Collection+JSON 文档
		
Collection+JSON 文档 对于这个设计,我们不再以可能的状态和转移为起点,相反,我们将从一个集合状态响应中可能元素的顶层布局开始.从这一点入手,其他细节可以随着设计向超媒体类型最底层属性的 ...
 - MongoDB学习(操作集合中的文档)
		
文档概念 文档的数据结构和JSON基本一样. 所有存储在集合中的数据都是BSON格式. BSON是一种类json的一种二进制形式的存储格式,简称Binary JSON. 插入文档 insert()方法 ...
 - package.json文档
		
之前在博客中写过一篇关于 " node.js的安装配置 " 的文章,里面有提到利用 gulp watch 来监听文档的变化.其中需要 package.json 文件才能实现效果,所 ...
 - 孤荷凌寒自学python第五十四天使用python来删除Firebase数据库中的文档
		
孤荷凌寒自学python第五十四天使用python来删除Firebase数据库中的文档 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数据库 ...
 - [Xcode 实际操作]七、文件与数据-(17)解析JSON文档
		
目录:[Swift]Xcode实际操作 本文将演示如何解析JSON文档. 项目中已添加一份JSON文档:menu.json { "menu": { "id": ...
 - [.NET] 打造一个很简单的文档转换器 - 使用组件 Spire.Office
		
打造一个很简单的文档转换器 - 使用组件 Spire.Office [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6024827.html 序 之前,& ...
 - Mongoose在向集合中插入文档时的集合命名问题
		
Mongoose使用结构化的模式应用到MongoDB集合,为MongoDB Node.js原生驱动程序提供了更多的功能和简化了数据库操作. 从创建连接到向数据库中写入一个条数据经历了以下步骤: 1.连 ...
 - 在SharePoint 2013 中使用文档库Scheduling (计划公布功能)
		
本文讲述在SharePoint2013 中使用文档库Scheduling (计划公布功能)的步骤和注意的事项. 文档库Scheduling (计划公布功能) 用于设定当文档通过审批后特定的时间区间内才 ...
 
随机推荐
- netcore3.1 webapi使用signalR
			
前言 今天尝试了一下signalR,感觉还不错,因为暂时用不到,就写一篇博文来记录搭建过程,以免以后给忘了,基于官方文档写的,不过官方没有webapi调用例子,就自己写了一下,大神勿喷 使用 1.创建 ...
 - MzzTxx——团队贡献分分配方案
			
项目 内容 这个作业属于哪个课程 2021春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 团队贡献分分配规则制定 我在这个课程的目标是 进一步提升工程化开发能力,积累团队协作经验,熟悉全栈 ...
 - SE_Work2_交点个数
			
项目 内容 课程:北航-2020-春-软件工程 博客园班级博客 要求:求交点个数 个人项目作业 班级:005 Sample GitHub地址 IntersectProject 一.PSP估算 在开始实 ...
 - ART-TEMPLATE的核心语法
			
模板引擎语法 核心方法 // 基于模板名渲染模板 template(filename, data); // 将模板源代码编译成函数 template.compile(source, options); ...
 - 【转载】深入理解OpenStack-手动制作qcow2镜像
			
深入理解OpenStack-手动制作qcow2镜像 2018-01-18 手动制作镜像 1 官方虽提供qcow2系统镜像,但对于有需求的企业来说,还是定制镜像比较靠谱,下面就手动定制一个镜像 给虚拟机 ...
 - reboot 就是 poweroff 然后power on
			
halt Shut down and halt the system poweroff Shut down and power-off the system reboot [ARG] Shut dow ...
 - 攻防世界-WEB-新手练习区
			
附:|>>>攻防世界-WEB-高手进阶区<<<|
 - Rust 泛型
			
Rust 泛型 泛型程序设计(generic programming)是程序设计语言的一种风格或范式.泛型允许程序员在强类型程序设计语言中编写代码时使用一些以后才指定的类型,在实例化时作为参数指明这些 ...
 - (全解析)屏幕尺寸,分辨率,像素,PPI之间到底什么关系?
			
(全解析)屏幕尺寸,分辨率,像素,PPI之间到底什么关系? 产品经理马忠信关注 22015.08.30 13:59:20字数 2,660阅读 52,661 今天我给大家来讲讲这几个咱们经常打交道的词到 ...
 - shell基础之bus实战(if 练习)
			
题目: 一条公交路线共30站,乘客上车需支付1元,之后每超过5站支付0.5元:最好可以实现"余额不足的提醒"和"逃票,漏刷卡的显示". 注意:需下载bc计算器 ...