我假设我的 PostgreSQL 表中有一个
jsonb
列 header_format
(结果是类型 json[]
,真的)。
列值如下所示:
{"{\"label\":\"SUPPLIER\",\"name\":\"supplier_name\",\"value\":\"VNS LTD\",\"show\":true,\"showPrint\":true,\"map\":\"\",\"input_type\":\"text\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"PRODUCT NAME\",\"name\":\"product_name\",\"value\":\"\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"INVOICE / DC #\",\"name\":\"invoice_no\",\"value\":\"cs/12/1222\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"INVOICE / DC DATE\",\"name\":\"invoice_date\",\"value\":\"2022-06-02\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"DATE_EXT\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"INVOICE QTY\",\"name\":\"invoice_qty\",\"value\":260,\"show\":true,\"showPrint\":true,\"input_type\":\"number\",\"map\":\"invoiceQty\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"No Need to Map\"}","{\"label\":\"IR #\",\"name\":\"ir\",\"value\":\"FY-23-09-1\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"GRN NO\",\"name\":\"grn_no\",\"value\":\"5032344565\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"GRN DATE\",\"name\":\"grn_date\",\"value\":\"2022-06-02\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"LAST_GR_DATE_EXT\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"R/M CODE\",\"name\":\"rmcode\",\"value\":\"CR11803C00MAN\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"EDS /Q /P #\",\"name\":\"eds\",\"value\":\"DE / EDS / 454\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"eds\",\"mapFrom\":\"product\",\"default\":true,\"note\":\"\"}","{\"label\":\"DATE\",\"name\":\"date\",\"value\":\"2022-09-13\",\"show\":true,\"showPrint\":true,\"input_type\":\"date\",\"map\":\"\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}","{\"label\":\"R/M\",\"name\":\"rm\",\"value\":\"DC01+LC-MA-RL\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"rm\",\"mapFrom\":\"product\",\"default\":true,\"note\":\"\"}","{\"label\":\"RECEIVED QTY\",\"name\":\"received_qty\",\"value\":260,\"show\":true,\"showPrint\":true,\"input_type\":\"number\",\"map\":\"invoiceQty\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"No Need to Map\"}","{\"label\":\"SHELF LIFE\",\"name\":\"shelf_life\",\"value\":\"20.11.2022\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"Shelf Life\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"No Need to Map\"}","{\"label\":\"MATERIAL TEXT\",\"name\":\"material_text\",\"value\":\"CP7B-DC01,1.18 x 31.5\",\"show\":true,\"showPrint\":true,\"input_type\":\"text\",\"map\":\"MATTEXT\",\"mapFrom\":\"header\",\"default\":true,\"note\":\"\"}"}
我正在
header_format
列中插入格式:
[{
label:'1',
value:'abc',
other...
},
{
label:'2',
value:'aab',
other...
}]
我想要一个与数组数据类型中的
"{label:'supplier'}"
匹配的行列表。
我尝试了以下方法:
方法一:
Database.rawQuery('select * from qasformones where header_format @> "{label:supplier}"')
方法二:
Database.rawQuery('select * from qasformones where header_format @> "[{label:supplier}]"')
我收到以下错误:
列“{label:supplier}”不存在
从 qasformones 中选择 *,其中 header_format @>“{label:supplier}” - 列“{show:true}”不存在
如何进行此查询?
此查询适用于您当前的表设计,包含 JSON 值数组 (
json[]
):
SELECT *
FROM qasformones q
WHERE EXISTS (
SELECT FROM unnest(q.header_format) js
WHERE js->>'label' = 'SUPPLIER' -- match case!
);
但是
json[]
通常不是您想要的。存储效率低下,而且该查询成本高昂且扩展性不佳。考虑将列转换为jsonb
包含数组或对象。
ALTER TABLE
是最快的方法 - 如果您有能力独占锁定表。参见:
但它不允许在
USING
子句中使用子查询表达式。因此,将功能包装在一个快速的临时函数中。 (在会话结束时自动删除。)
CREATE FUNCTION pg_temp.jsb_transform (json[])
RETURNS jsonb
LANGUAGE sql AS
$func$
SELECT jsonb_agg(js) FROM unnest($1) js;
$func$;
ALTER TABLE qasformones
ALTER COLUMN header_format TYPE jsonb USING pg_temp.jsb_transform(header_format);
那么我建议:
VACUUM FULL ANALYZE qasformones;
并创建索引:
CREATE INDEX qasformones_header_format_gin_idx ON qasformones USING gin (header_format jsonb_path_ops);
关于:
现在您的查询可以是:
SELECT *
FROM qasformones q
WHERE header_format @> '[{"label":"SUPPLIER"}]';
或者,在 Postgres 12+ 中使用 SQL/JSON 路径表达式
SELECT *
FROM qasformones q
WHERE header_format @? '$ ? (@.label == "SUPPLIER")';
jsonb_populate_recordset()
将键分解为专用的常规表列可能会更有效,请参阅:
这将导致当前
json[]
中的 N 个数组元素有 N 行。可能是一对多的设计。相关: