postgresql 在postgre中使用$.**递归表达式时出现重复结果

tquggr8v  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(155)

我有一个timescaleDB,我试图使用jsonb_path_query查询,但我得到重复的结果。
表格结构:

SELECT * FROM public.meta_table_cum_115

个字符
正如你所看到的,这是一个嵌套结构。
我在PostgreSQL Website上找到了一封关于这个问题的邮件。据我所知,这是一个错误,但我在任何地方都找不到解决方案。
当我运行查询时:

select sum(count) as count,label from (select count('label'),
jsonb_path_query(COLUMNNAME, '$.** ? (@.name == "AGE" && @.label!=null)') -> 'label' as label
          
from TABLENAME 
WHERE  TIME BETWEEN to_timestamp(0)  AND to_timestamp(8640000000000)  GROUP BY  label ) as grouped group by label


我得到的结果:

"count" "label"
1   """12"""
2   """18"""
3   """19"""
1   """31"""
2   """39"""
1   """48"""


但是当我运行这个查询时:

select sum(count) as count,label from (select count('label'),
jsonb_path_query(COLUMNNAME, '$.** ? (@.name == "PEOPLE" && @.label!=null)') -> 'label' as label
          
from TABLENAME 
WHERE  TIME BETWEEN to_timestamp(0)  AND to_timestamp(8640000000000)  GROUP BY  label ) as grouped group by label


测试结果:

"count" "label"
28  """toast"""
14  """person"""


但实际结果与表中不同,必须是:

"count" "label"
14  """toast"""
7   """person"""


然后我从**$.* 部分($.*)中删除了一个 * char,它可以工作,结果是:

"count" "label"
14  """toast"""
7   """person"""


我不知道现在该怎么办。我是否必须改变查询的方式,或者对嵌套或非嵌套结构进行不同的查询($.**或$.*)?

rhfm7lfc

rhfm7lfc1#

Docs
SQL/JSON路径表达式有两种处理结构错误的模式:
lax(默认值)-路径引擎隐式地将查询的数据调整为指定的路径。任何剩余的结构性错误都将被抑制并转换为空SQL/JSON序列。
strict -如果发生结构性错误,则引发错误。
还有:
当使用lax模式时,.**访问器可能会导致令人惊讶的结果。
还有:
为了避免意外的结果,我们建议只在严格模式下使用.**访问器。以下查询只选择每个HR值一次:strict $.**.HR
由于默认模式是lax,在您的情况下,.**访问器将导致两次值:

select jsonb_path_query(COLUMNNAME, '$.** ? (@.name == "PEOPLE" && @.label!=null)') -> 'label' as label
from meta_table_cum_115

字符串
与此类似:

select jsonb_path_query(COLUMNNAME, 'lax $.** ? (@.name == "PEOPLE" && @.label!=null)') -> 'label' as label
from meta_table_cum_115


对于数据:

create table meta_table_cum_115 (
  time   timestamp,  
  COLUMNNAME  jsonb
);

insert into meta_table_cum_115 values
('2023-12-22 12:25:31.001244', '{"1": [{"results": {"2": { "name": "AGE", "label": "12"}}, "name": "PEOPLE", "label": "toast"}]}');


威尔回来了:

label
"toast"
"toast"


因此,为了避免重复,请使用文档中建议的严格模式:

select jsonb_path_query(COLUMNNAME, 'strict $.** ? (@.name == "PEOPLE" && @.label!=null)') -> 'label' as label
from meta_table_cum_115


将得到正确的数据:

label
"toast"


Demo here

相关问题