在逗号分隔的列中搜索多个值(PostgreSQL)

时间:2019-12-12 09:16:13

标签: postgresql

我需要获取5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5列中存在这些(categories_id)值的所有记录。 我需要在categories_id中搜索的值可以是多个,因为它来自表单。

+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id                                   | name        | alias       | description | categories_id                                                                                                                                                 |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 5565c08d-9f18-4b76-9cae-4a8261af48f5 | Honeycolony | honeycolony | null        | ["5565bffd-7f64-494c-8950-4bef61af48f5"]                                                                                                                      |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| c8f16660-32cf-11e6-b73c-1924f891ba4d | LOFT        | loft        | null        | ["5565bffd-25bc-4b09-8a83-4bef61af48f5","5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]                                        |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 5565c17f-80d8-4390-aadf-4a8061af48f5 | Fawn Shoppe | fawn-shoppe | null        | ["5565bffd-25bc-4b09-8a83-4bef61af48f5","5565bffd-0744-4740-81f5-4bef61af48f5","5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"] |
+--------------------------------------+-------------+-------------+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------+

我有此功能,可以用作in_array函数php。

CREATE OR REPLACE FUNCTION public.arraycontain(
    x json,
    y json)
    RETURNS boolean
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE 
AS $BODY$
  DECLARE a text;b text;
  BEGIN
    FOR a IN SELECT json_array_elements_text($1)
    LOOP
      FOR b IN SELECT json_array_elements_text($2)
      LOOP
        IF a = b THEN
          RETURN TRUE;
        END IF;
      END LOOP;
    END LOOP;
    RETURN FALSE ;
  END;
  $BODY$;

ALTER FUNCTION public.arraycontain(json, json)
    OWNER TO postgres;

但是当我这样做时:

select * from "stores" 
where arrayContain(stores.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]') 

它显示

  

错误:类型json的输入语法无效
  详细信息:输入字符串   意外结束。
  上下文:JSON数据,第1行:SQL状态:22P02

这是sqlfiddle(我无法在小提琴中更新arraycontain函数。)

我从小提琴获得的预期输出是,如果使用此值Furbish Studio,Fawn Shoppe AND LOFT进行搜索,它应该返回最后三行,即["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"])

我愿意接受任何建议。 我也在下面尝试了此查询,但返回空。

select id
from stores
where string_to_array(categories_id,',') && array['5565bffd-cd78-4e6f-ae13-4bef61af48f5','5565bffd-b1c8-4556-ae5d-4bef61af48f5'];

编辑:

此代码实际上是用于过滤数据的过滤器。因此,如果我仅使用类别进行过滤,它将无法正常工作,但是如果之前存在一个查询,它将可以正常工作

select * from "stores" 
    where name like '%ab%' and  arrayContain(stores.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]') 

让我感到惊讶的是,如果{<1}}小于<2,则必须包含两个以上的字符,这将引发错误。有什么问题。

2 个答案:

答案 0 :(得分:1)

Click: demo:db<>fiddle

您可以使用?|运算符,该运算符采用jsonb数组(在这种情况下为您的列)并检查text数组是否包含任何元素:

SELECT
    *
FROM 
    mytable
WHERE categories_id ?| '{5565bffd-b1c8-4556-ae5d-4bef61af48f5,5565bffd-cd78-4e6f-ae13-4bef61af48f5}'

如果您的categories_id的类型不是json(错误消息说的是),而是简单的text数组,则可以直接使用比较两个text数组&&运算符:

Click: demo:db<>fiddle

SELECT
    *
FROM 
    mytable
WHERE categories_id && '{5565bffd-b1c8-4556-ae5d-4bef61af48f5,5565bffd-cd78-4e6f-ae13-4bef61af48f5}'

答案 1 :(得分:1)

您的代码似乎可以正常工作,所以也许sqlfiddle是问题所在。 尝试将模式构建部分中的分隔符更改为/(而不是;),并确保您具有适用于Postgresql的正确版本。 9.3不支持json_array_elements_text(在这种情况下,您可以改用json_array_elements)。

还要跳过select语句中的“。

看这里http://sqlfiddle.com/#!17/918b75/1

您的数据可能有误。也许category_id在某处是一个空字符串。

尝试此操作以查看有问题的数据。

do $$ 
declare 
    r record;
    b boolean;
begin
for r in (select * from stores) loop
b:= arrayContain(r.categories_id::JSON,'["5565bffd-b1c8-4556-ae5d-4bef61af48f5","5565bffd-cd78-4e6f-ae13-4bef61af48f5"]') ;
end loop;
exception
    when others 
        then raise notice '%,%',r,r.categories_id;
        return;
end;
$$

最诚挚的问候。
比尼亚尼