【问题标题】:Select JSON value from a EAV structure result set从 EAV 结构结果集中选择 JSON 值
【发布时间】:2019-01-18 07:05:05
【问题描述】:

给定一个 EAV 结构中的结果集,例如:

id   | attributeName  | stringValue | intValue  | BooleanValue
---------------------------------------------------------------
1       stringFoo            v1
1       stringFooList        v2   
1       stringFooList        v3
1       intFoo                           10
1       intFooList                       10
1       intFooList                       20
1       booleanFoo                                     true
1       booleanFooList                                 true 
1       booleanFooList                                 true

如何将所有属性和值对选择为 JSON/JSONB 格式的单个值,例如:

{
    "stringFoo"         : "v1" , 
    "stringFooList"     : ["v2","v3"] ,
    "intFoo"            : 10 ,
    "intFooList"        : [10,20],
    "booleanFoo"        : true,
    "booleanFooList"    : [true,true]
}

如果一个属性有多个属性值,例如stringFooList,它会将其格式化为JSON数组。

我使用的是 PostgreSQL 9.6

【问题讨论】:

    标签: postgresql jsonb entity-attribute-value


    【解决方案1】:

    你可以这样做:

    select id, jsonb_object_agg(att, value)
    from (
      select id, 
             attributename as att, 
             case 
               when count(*) > 1 then 
                   jsonb_agg(coalesce(stringvalue,intvalue::text,booleanvalue::text)) 
               else 
                  to_jsonb(min(coalesce(stringvalue,intvalue::text,booleanvalue::text)))
             end as value
      from eav
      group by id, attributename
    ) t
    group by id;
    

    内部选择将多个值聚合为 JSON 数组,将单个值聚合为 JSON 标量值。然后外部查询构建所有行的单个 JSON 值。

    在线示例:https://rextester.com/TLCRN79815

    【讨论】:

    • 感谢您的宝贵时间。听起来不错。如果结果集非常大,在我的情况下使用 json 或 jsonb 有什么区别吗?
    • JSONB 更高效
    【解决方案2】:

    @a_horse_with_no_name 的回答给了我一个好的开始。我扩展了他/她的答案并提出以下查询,以便 JSON 数组中的元素具有与 PostgreSQL 中定义的数据类型相同的数据类型。

    select id, jsonb_object_agg(att, 
        case 
          when strval is not null then strval
          when intvalue is not null then intvalue
          else boolVal
         end 
        )
    from (
      select id, 
             attributename as att,  
             case when count(*) > 1 then 
                jsonb_agg(stringvalue) filter (where stringvalue is not null) 
             else 
                to_jsonb(min(stringvalue) filter (where stringvalue is not null))     
             end as strVal, 
    
             case when count(*) > 1 then 
                jsonb_agg(intvalue) filter (where intvalue is not null) 
             else 
                to_jsonb(min(intvalue) filter (where intvalue is not null))     
             end as intvalue, 
    
             case when count(*) > 1 then 
                jsonb_agg(booleanvalue) filter (where booleanvalue is not null) 
             else 
                to_jsonb(bool_and(booleanvalue) filter (where booleanvalue is not null))     
             end as boolVal
      from eav
      group by id, attributename
    ) t
    group by id;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-14
      • 1970-01-01
      相关资源
      最近更新 更多