想象一下,您有人们发布广告的网站。因此,每个广告都有一些选定的属性,例如汽车具有不同的引擎类型,齿轮,颜色等。用户在提交列表之前选择这些属性。 我在列表中以jsonb格式存储选定的属性,查看数据列:
因此,每个商家信息都包含以下数据:
{
"properties":[
{
"id":"1",
"value_id":"1"
},
{
"id":"2",
"value_id":"5"
},
{
"id":"3",
"value_id":"9"
},
{
"id":"4",
"value":"2.0"
},
{
"id":"7",
"value":"2017"
},
{
"id":"6",
"value":"180.000"
}
]
}
现在,问题是:
1)如何根据json中的id和值来过滤列表?例如,显示列表,其中id = 2,它的值= 5 AND id = 3,它的值= 9,依此类推。我不需要 OR ,我需要 AND 。因此,按多个id和值过滤数据。
2)第一点+比较id和值(大于或小于)的能力。
答案 0 :(得分:0)
回答第一点,这可能是我第一次使用jsonb[]
:
t=# with c(a,j) as (values(18,'{
"properties":[
{
"id":"1",
"value_id":"1"
},
{
"id":"2",
"value_id":"5"
},
{
"id":"3",
"value_id":"9"
},
{
"id":"4",
"value":"2.0"
},
{
"id":"7",
"value":"2017"
},
{
"id":"6",
"value":"180.000"
}
]
}'::jsonb), (19,'{"properties":[{"id": "1", "value_id": "1"}]}'))
, m as (select a, array_agg(jb.value)::jsonb[] ar from c, jsonb_array_elements(j->'properties') jb group by a)
select a
from m
where '{"id": "1", "value_id": "1"}'::jsonb = any(ar)
and '{"id": "3", "value_id": "9"}'::jsonb = any(ar);
a
----
18
(1 row)
并且对于第二个要求 - 它不会那么简短,因为你需要进行比较(从而解析json):
t=# with c(a,j) as (values(18,'{
"properties":[
{
"id":"1",
"value_id":"1"
},
{
"id":"2",
"value_id":"5"
},
{
"id":"3",
"value_id":"9"
},
{
"id":"4",
"value":"2.0"
},
{
"id":"7",
"value":"2017"
},
{
"id":"6",
"value":"180.000"
}
]
}'::jsonb), (19,'{"properties":[{"id": "1", "value_id": "1"}]}'))
, m as (select a, jb.value->>'id' id,jb.value->>'value_id' value_id from c, jsonb_array_elements(j->'properties') jb)
, n as (select m.*, count(1) over (partition by m.a)
from m
join c on c.a = m.a and ((id::int >= 1 and value_id::int <2) or (id::int >2 and value_id::int <= 9)))
select distinct a from n
where count > 1;
a
----
18
(1 row)
基本想法使用OR
获取可能的行,然后检查是否满足所有OR
条件