如何确定范围列表是否包含指定的整数
How determine if range list contains specified integer
产品类型 table 包含产品类型。一些 ID 可能会丢失:
create table artliik (liiginrlki char(3) primary key);
insert into artliik values('1');
insert into artliik values('3');
insert into artliik values('4');
...
insert into artliik values('999');
属性 table 包含以逗号分隔的类型列表。
create table strings ( id char(100) primary key, kirjeldLku chr(200) );
insert into strings values ('item1', '1,4-5' );
insert into strings values ('item2', '1,2,3,6-9,23-44,45' );
类型可以指定为单个整数,e.q 1,2,3 或范围如 6-9 或 23-44
列表可以同时包含它们。
如何获取给定类型的所有属性。
查询
select id
from artliik
join strings on ','||trim(strings.kirjeldLku)||',' like '%,'||trim(artliik.liiginrlki)||',%'
returns 仅限单个整数列表的日期。
如何更改 join 以便也返回列表中的类型范围,如 6-9?
当量。 f 列表包含 6-9,类型 6、7、8 和 9 应包含在报告中。
使用 Postgres 13。
我建议使用类似于 unnest
的辅助函数来支持范围。
更正函数
create or replace function unnest_ranges(s text)
returns setof text language sql immutable as
$$
with t(x) as (select unnest(string_to_array(s, ',')))
select generate_series
(
split_part(x, '-', 1)::int,
case when x ~ '-' then split_part(x, '-', 2)::int else x::int end,
1
)::text
from t;
$$;
然后你可以'normalize'tablestrings
加入。
select *
from artliik a
join (select id, unnest_ranges(kirjeldLku) from strings) as t(id, v)
on a.liiginrlki = v;
函数定义的使用当然是可选的。我更喜欢它,因为它的功能是通用的和可重用的。
dbfiddle.uk demo 仅适用于 pg14,因为只有 pg14 具有多范围数据类型。但可自定义的 icu 整理在 pg13 中有效。
整理文档:https://www.postgresql.org/docs/current/collation.html
想法:创建一个多范围文本数据类型,它将根据数值对数值进行排序。像 'A-21' < 'A-123'.
CREATE COLLATION testcoll_numeric (
provider = icu,
locale = '@colNumeric=yes'
);
CREATE TYPE textrange AS RANGE (
subtype = text,
multirange_type_name = mulitrange_of_text,
COLLATION = testcoll_numeric
);
所以
SELECT
mulitrange_of_text (textrange ('1'::text, '11'::text)) @> '9'::text AS contain_9;
应该return正确.
artliik table 结构保持不变,但字符串 table 需要稍作更改。
CREATE temp TABLE strings (
id text PRIMARY KEY,
kirjeldLku mulitrange_of_text
);
然后查询:
SELECT DISTINCT
strings.id
FROM
artliik,
strings
WHERE
strings.kirjeldLku @> liiginrlki::text
ORDER BY
1;
产品类型 table 包含产品类型。一些 ID 可能会丢失:
create table artliik (liiginrlki char(3) primary key);
insert into artliik values('1');
insert into artliik values('3');
insert into artliik values('4');
...
insert into artliik values('999');
属性 table 包含以逗号分隔的类型列表。
create table strings ( id char(100) primary key, kirjeldLku chr(200) );
insert into strings values ('item1', '1,4-5' );
insert into strings values ('item2', '1,2,3,6-9,23-44,45' );
类型可以指定为单个整数,e.q 1,2,3 或范围如 6-9 或 23-44 列表可以同时包含它们。
如何获取给定类型的所有属性。 查询
select id
from artliik
join strings on ','||trim(strings.kirjeldLku)||',' like '%,'||trim(artliik.liiginrlki)||',%'
returns 仅限单个整数列表的日期。 如何更改 join 以便也返回列表中的类型范围,如 6-9? 当量。 f 列表包含 6-9,类型 6、7、8 和 9 应包含在报告中。
使用 Postgres 13。
我建议使用类似于 unnest
的辅助函数来支持范围。
更正函数
create or replace function unnest_ranges(s text)
returns setof text language sql immutable as
$$
with t(x) as (select unnest(string_to_array(s, ',')))
select generate_series
(
split_part(x, '-', 1)::int,
case when x ~ '-' then split_part(x, '-', 2)::int else x::int end,
1
)::text
from t;
$$;
然后你可以'normalize'tablestrings
加入。
select *
from artliik a
join (select id, unnest_ranges(kirjeldLku) from strings) as t(id, v)
on a.liiginrlki = v;
函数定义的使用当然是可选的。我更喜欢它,因为它的功能是通用的和可重用的。
dbfiddle.uk demo 仅适用于 pg14,因为只有 pg14 具有多范围数据类型。但可自定义的 icu 整理在 pg13 中有效。
整理文档:https://www.postgresql.org/docs/current/collation.html
想法:创建一个多范围文本数据类型,它将根据数值对数值进行排序。像 'A-21' < 'A-123'.
CREATE COLLATION testcoll_numeric (
provider = icu,
locale = '@colNumeric=yes'
);
CREATE TYPE textrange AS RANGE (
subtype = text,
multirange_type_name = mulitrange_of_text,
COLLATION = testcoll_numeric
);
所以
SELECT
mulitrange_of_text (textrange ('1'::text, '11'::text)) @> '9'::text AS contain_9;
应该return正确.
artliik table 结构保持不变,但字符串 table 需要稍作更改。
CREATE temp TABLE strings (
id text PRIMARY KEY,
kirjeldLku mulitrange_of_text
);
然后查询:
SELECT DISTINCT
strings.id
FROM
artliik,
strings
WHERE
strings.kirjeldLku @> liiginrlki::text
ORDER BY
1;