在项目的数据库设计中,可能会碰到不确定列的情况。 使用JSON 格式来保存这种不确定列的数据, 是一种比较灵活且方便的做法。 

 

比如一张表记录学生的成绩。

 

 

如果列上的学科是不确定的, 比如有的学生有物理成绩, 有的学生有生物成绩,那么我们可能会考虑将表设计成:

 

 

但这样,可能就会在查询的时候,遇到麻烦。比如我想知道数学成绩是4分的有哪些学生?

类似的问题, 我在项目中使用的做法是写了一个自定义的函数: fun_scale_matchJsonPattern 


 1 /*
 2  *  Author : Harvey Hu
 3  *  Created At :2020-6-5
 4  *  Description : 按指定单个模式判断匹配JSON是否满足(>= 条件即为匹配)
 5  *  Return =1 匹配 ; =0 不匹配
 6  */
 7 CREATE FUNCTION [dbo].[fun_scale_matchJsonPattern]
 8 (
 9      @pattern nvarchar(1000),  -- 单个模式
10      @input nvarchar(1000)
11  ) returns int
12  begin
13      Declare @targetScore int = 0; 
14      Declare @actualScore int = 0; 
15      Declare @result int = 0; 
16       
17      select @targetScore= count(*) from OPENJSON(@pattern) a
18 
19      select @actualScore = count(1)
20         from OPENJSON(@pattern) a
21            inner join OPENJSON(@input) b on a.[key]= b.[key] and a.[value] = b.[value]
22 
23      IF @targetScore = @actualScore
24         SET @result = 1
25      
26      return @result
27 
28  end

 

 使用的示例如下

1 select  
2    *
3 from dbo.[学生成绩表]
4 where 
5    dbo.fun_scale_matchJsonPattern([成绩],'{"数学":"4"}')=1

 

简单的来说,就是比较条件的数量和匹配的条件数量是否一致,如果一致则认为满足。

这种方式的好处是, 可以使用 'and' 逻辑去匹配多个条件;不好的地方在于只能判断‘相等逻辑’,不适用于‘大于’‘小于’等其他的二元逻辑。 不过由于工作上够用了, 所以没有做更多的扩展。如果有需要可以在评论中留言。

 

基于上述内容, 下面这个是‘多个条件取其一即可满足’的实现

 1  /*
 2  *  Author : Harvey Hu
 3  *  Created At :2020-6-5
 4  *  Description : 按指定多个模式判断匹配JSON是否满足(只要有其中之一满足即为匹配)
 5  *  Return =1 匹配 ; =0 不匹配
 6  */
 7 CREATE FUNCTION [dbo].[fun_scale_matchJsonPatterns]
 8 (
 9     @patterns nvarchar(1000),  -- 数组JSON格式
10     @input nvarchar(1000)
11  ) returns int  
12  as
13  begin
14     DECLARE @key nvarchar(50)
15     DECLARE @value nvarchar(1000)
16     DECLARE @type int
17     DECLARE @result int =0
18 
19    DECLARE jsonCursor CURSOR for 
20    select * from OPENJSON(@patterns)
21 
22    OPEN  jsonCursor
23    fetch next from jsonCursor into @key,@value ,@type
24 
25    while @@fetch_status=0           --判断是否成功获取数据   进入循环
26    begin
27          if @type = 5  and  dbo.[fun_scale_matchJsonPattern](@value,@input)=1  -- object
28               set @result = 1
29    fetch next from jsonCursor into @key,@value ,@type
30    end
31 
32 
33    CLOSE jsonCursor
34 
35    return @result
36  end

 

使用了游标, 所以性能上可能会有影响。 期待改进!

posted on 2021-07-07 15:50  Weizheng  阅读(682)  评论(0编辑  收藏  举报