首页 > 解决方案 > 在列字段中查找相同的标签 PostgreSQL

问题描述

嗨,我需要在列字段中找到相同的标签。

我的查询:

select *, from 
(SELECT *,  string_agg(DISTINCT "tags".tag, ',') as tags_field
            from restaurants
            left JOIN tags on rest.rest_id = tags.rest_id
            GROUP by rest_id) x

它返回了很多列,我只需要离开,并寻求帮助

rest_id  tags_field
1        "Sussi,Burger"
2        "Sussi,Pizza"
3        "Seafood"
4        "Sussi,Vok,Beer"
5        "Sussi, Pizza"

从后端我将搜索标签,Sussi在这种情况下它应该返回 1,2,4,5 行,如果我需要Sussi,Pizza它应该只返回 1,2 ,并且序列应该无关紧要。

例如,我在 sqlite 上尝试过,我用正则表达式解决了它,但是如何在 posgtresql 上做同样的事情

tags_field REGEXP ^(?=.*\bPizza\b)(?=.*\bSushi\b)

标签: pythonregexdatabasepostgresql

解决方案


您可以将文本列转换为数组并使用数组比较。

SELECT *
FROM
    (SELECT rest_id, string_to_array(trim(tags_field), ',') as tags_field FROM data) data
WHERE
    ARRAY['Pizza','Sussi'] <@ tags_field; -- query clause
-- THIS RETURNS
-- 2 {Sussi,Pizza}

<@手段包含在 中。这意味着tags_field必须有 Pizza 和 Sussi 才能成立。由于它是一个数组,因此顺序无关紧要。所以

ARRAY['Sussi','Pizza'] = ARRAY['Pizza','Sussi'] -- for the *is contained by* validation

如果你使用ARRAY['Sussi'] <@ tags_field,你会得到 ids: 1,2,4,5

由于 Pizza 前面有空格,因此不会搜索“Pizza”。

' Pizza' != 'Pizza' -- Remember PostgreSQL is case sensitive and every space matters.

要查找每个 Pizza,您必须对数据进行预处理并删除不必要的空格。不推荐但可行

SELECT *
FROM(
    SELECT 
        rest_id,
        string_to_array(
            trim(-- Remove spaces after and before text
                regexp_replace(
                    regexp_replace(
                        regexp_replace(
                            tags_field,
                            '\s+', ' ', 'g'), -- Replace multiple spaces to one space.
                        ', ',',','g' -- Remove space after coma
                    ),
                    ' ,',',','g' -- Remove space before coma
                )
            ),
            ',' -- Delimitador for array
        )as tags_field 
    FROM data
) data_mod
WHERE
    ARRAY['Pizza','Sussi'] <@ tags_field; -- query clause
-- THIS RETURNS
-- 2 {Sussi,Pizza}
-- 5 {Sussi,Pizza}

使用前面的查询,您将获得 ids 2 和 5,因为不再有带有空格的“Pizza”。

正确的方法是通过更新来修复您的流氓空间,并且更好地使用array而不是textfor tags_field,但这array部分意味着更改您的数据库结构,所以......我们将继续进行更新:

UPDATE data SET tags_field = trim(-- Remove spaces after and before text
    regexp_replace(
        regexp_replace(
            regexp_replace(
                tags_field,
                '\s+', ' ', 'g'), -- Multiple spaces to one space.
            ', ',',','g' -- remove space after coma
        ),
        ' ,',',','g' -- remove space before coma
    )
);

随着更新,您的查询将是:

SELECT *
FROM
    (SELECT rest_id, string_to_array(tags_field, ',') as tags_field FROM data) data
WHERE
    ARRAY['Pizza','Sussi'] <@ tags_field;

无需修剪。

如果您更改表结构并使用array而不是text查询会更容易:

SELECT rest_id, tags_field
FROM data
WHERE
    ARRAY['Pizza','Sussi'] <@ tags_field;

推荐阅读