PostgreSQL 中匹配逗号分隔的ID字符串, 使用 array,string_to_array,any

PostgreSQL 中匹配逗号分隔的ID字符串, 使用 array,string_to_array,any

场景:两张表,books 和 tags 表,一个 book 对应多个 tag。但是 book 把 tag 信息存在一个字符串中,用逗号分隔。

如何匹配这种数据

代码演示


-- 建表
create table books(
    id varchar(32),
    name varchar(256),
    tags varchar(256)
);


create table tags(
    id varchar(32),
    name varchar(256)
);


-- 测试数据
INSERT INTO tags VALUES('01', 'Tag01');
INSERT INTO tags VALUES('02', 'Tag02');
INSERT INTO tags VALUES('03', 'Tag03');
INSERT INTO tags VALUES('04', 'Tag04');

insert into books VALUES('01', 'Book01', '01');
insert into books VALUES('02', 'Book02', '01,02');
insert into books VALUES('03', 'Book03', '01,02,03');



-- 查询1
-- 找到任一匹配的标签
-- STRING_TO_ARRAY 字符串--> Array
-- ANY(Array[]) 满足 Array 的任一元素。 注意:ANY 必须放在表达式的右侧。
SELECT
    * 
FROM
    books b
    LEFT JOIN tags T ON T."id" = ANY ( STRING_TO_ARRAY( b.tags, ',' ) )

-- 结果
-- 可以看到结果,每本书有几个标签就有几条数据。
-- 但这可能不是我们希望的结果形式
-- 01  Book01  01        01  Tag01
-- 02  Book02  01,02     01  Tag01
-- 02  Book02  01,02     02  Tag02
-- 03  Book03  01,02,03  01  Tag01
-- 03  Book03  01,02,03  02  Tag02
-- 03  Book03  01,02,03  03  Tag03

-- 查询2
-- 按照书分组,使用 array_agg 处理标签
SELECT
    b.ID,
    b.NAME,
    array_agg(t.name)
FROM
    books b
    LEFT JOIN tags t ON t."id" = ANY ( STRING_TO_ARRAY( b.tags, ',' ) ) 
GROUP BY
    b.ID,
    b.NAME 
ORDER BY
    b.ID

-- 结果
-- 01  Book01  {Tag01}
-- 02  Book02  {Tag01,Tag02}
-- 03  Book03  {Tag01,Tag02,Tag03}

posted @ 2023-01-11 12:28  吴思老  阅读(1857)  评论(0编辑  收藏  举报