bjo*_*831 6 arrays postgresql where set-returning-functions jsonb
我JSONB在PostgreSQL中有一个对象:
'{"cars": ["bmw", "mercedes", "pinto"], "user_name": "ed"}'
Run Code Online (Sandbox Code Playgroud)
我试图在a的子句中使用其中"cars"数组的值:WHERESELECT
SELECT car_id FROM cars WHERE car_type IN ('bmw', 'mercedes', 'pinto');
Run Code Online (Sandbox Code Playgroud)
这将正确返回值1,2和3 - 请参阅本文底部的表格设置.
目前,在我的功能中我这样做:
(1) Extract the "cars" array into a variable `v_car_results`.
(2) Use that variable in the `WHERE` clause.
Pseudo code:
DECLARE v_car_results TEXT
BEGIN
v_car_results = '{"cars": ["bmw", "mercedes", "pinto"], "user_name": "ed"}'::json#>>'{cars}';
-- this returns 'bmw', 'mercedes', 'pinto'
SELECT car_id FROM cars WHERE car_type IN ( v_car_results );
END
Run Code Online (Sandbox Code Playgroud)
但是,该SELECT语句不返回任何行.我知道它正在阅读这3种车型作为单一类型.(如果我只car_type在"cars"元素中包含一个,则查询工作正常.)
我将如何对待这些值作为一个数组里面WHERE的条款?
我尝试过其他一些东西:
该ANY条款.
各种铸造尝试.
这些查询:
SELECT car_id FROM cars
WHERE car_type IN (json_array_elements_text('["bmw", "mercedes", "pinto"]'));
...
WHERE car_type IN ('{"cars": ["bmw", "mercedes", "pinto"], "user_name": "ed"}':json->>'cars');
Run Code Online (Sandbox Code Playgroud)这感觉就像是我想念的简单.但是我在这个兔子洞里掉了下来.(也许我甚至不应该使用::json#>>运算符?)
CREATE TABLE cars (
car_id SMALLINT
, car_type VARCHAR(255)
);
INSERT INTO cars (car_id, car_type)
VALUES
(1, 'bmw')
, (2, 'mercedes')
, (3, 'pinto')
, (4, 'corolla');
SELECT car_id FROM cars
WHERE car_type IN ('bmw', 'mercedes', 'pinto'); -- Returns Values : 1, 2, 3
Run Code Online (Sandbox Code Playgroud)
假设当前的Postgres版本为9.5,因为它没有指定.
使用set-returning函数jsonb_array_elements_text()(作为表函数!)并加入到结果中:
SELECT c.car_id
FROM jsonb_array_elements_text('{"cars": ["bmw", "mercedes", "pinto"]
, "user_name": "ed"}'::jsonb->'cars') t(car_type)
JOIN cars c USING (car_type);
Run Code Online (Sandbox Code Playgroud)
从对象中提取JSON数组jsonb->'cars',并将生成的JSON数组(仍为数据类型jsonb)传递给该函数.(操作员#>也可以完成这项工作.)
旁白:::json#>>不仅仅是一个运营商.这是对json(::json)的强制转换,然后是运算符#>>.你也不需要.
生成的类型可以text方便地匹配您的列类型varchar(255),因此我们不需要类型转换.并指定列名car_type以允许USING在连接条件中使用语法缩写.
这种形式更短,更优雅,通常比使用IN ()或的替代品快一点= ANY()- 这也可以.您的尝试非常接近,但您需要带有子查询的变体.这可行:
SELECT car_id FROM cars
WHERE car_type IN (SELECT json_array_elements_text('["bmw", "mercedes", "pinto"]'));
Run Code Online (Sandbox Code Playgroud)
或者,清洁:
SELECT car_id FROM cars
WHERE car_type IN (SELECT * FROM json_array_elements_text('["bmw", "mercedes", "pinto"]'));
Run Code Online (Sandbox Code Playgroud)
详细说明:
有关: