从列中读取数据并动态生成缺失行的函数
Function that will read the data from a column and generate the missing rows dynamically
我有一个函数,return 从 table 中缺少 documentno,但是 documentno 列中数据左侧部分的长度是手动传递的,右侧部分有一些歧义。
现在我想要一个函数,它将从列 (documentno) 和 return 动态读取丢失的 documentno 中读取数据。
我的查询:
CREATE TABLE c_order (
"order_id" VARCHAR(22),
"documentno" VARCHAR(20)
);
INSERT INTO c_order
("order_id", "documentno")
VALUES
('100001120', 'AGB/2021/02050'),
('100001124' ,'AGB/2021/02055'),
('100001120', 'PROFS/2021/02056'),
('100001124' ,'PROF/2021/02060'),
('100001125' ,'PROF/2021/02065'),
('100001120', 'PROFS/2020/02050_A'),
('100001124' ,'PROFS/2020/02055_A'),
('100001120', 'PROFS/2021/02056'),
('100001124' ,'PROFSS/2021/0206010'),
('100001125' ,'PROFSS/2021/0206020')
with cte as (
select left(documentno,13) lpart,
regexp_replace(split_part(documentno, '/', 3), '[^0-9]', '', 'g')::int as num
from c_order
), minmax as (
select lpart, min(num) minpart, max(num) maxpart
from cte
group by lpart
)
select lpart||t.doc_no as missing_doc_no
from minmax m
cross join generate_series(minpart, maxpart) as t(doc_no)
where not exists (select *
from c_order c
where regexp_replace(split_part(c.documentno, '/', 3), '[^0-9]', '', 'g')::int = t.doc_no)
我的 fiddle : https://dbfiddle.uk/?rdbms=postgres_12&fiddle=0d3a6a647c6ef2a9063c7f3289446998
我该怎么做?
我没有写完整的解决方案,因为你已经做对了,但这里是如何使用正则表达式动态获取最后一个数字部分的方法:
select
substring(documentno, '\w*\/\d*\/') constantpart ,
max(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Maxnumericpart,
min(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Minnumericpart
from c_order co
group by constantpart
好的,这里是完整的解决方案:
select tt.constantpart || LPAD(t.doc_no::text,ll,'0') missingdocumentNo
from
(select
substring(documentno, '\w*\/\d*\/') constantpart ,
max(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Maxnumericpart,
min(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Minnumericpart,
length(min(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))) ll
from c_order co
group by constantpart
) tt
cross join generate_series(Minnumericpart, Maxnumericpart) as t(doc_no)
where not exists (
select 1
from c_order co2
where substring(co2.documentno, '\w*\/\d*\/\d*') = tt.constantpart || LPAD(t.doc_no::text,ll,'0')
)
order by missingdocumentNo;
db<>fiddle here
我有一个函数,return 从 table 中缺少 documentno,但是 documentno 列中数据左侧部分的长度是手动传递的,右侧部分有一些歧义。 现在我想要一个函数,它将从列 (documentno) 和 return 动态读取丢失的 documentno 中读取数据。
我的查询:
CREATE TABLE c_order (
"order_id" VARCHAR(22),
"documentno" VARCHAR(20)
);
INSERT INTO c_order
("order_id", "documentno")
VALUES
('100001120', 'AGB/2021/02050'),
('100001124' ,'AGB/2021/02055'),
('100001120', 'PROFS/2021/02056'),
('100001124' ,'PROF/2021/02060'),
('100001125' ,'PROF/2021/02065'),
('100001120', 'PROFS/2020/02050_A'),
('100001124' ,'PROFS/2020/02055_A'),
('100001120', 'PROFS/2021/02056'),
('100001124' ,'PROFSS/2021/0206010'),
('100001125' ,'PROFSS/2021/0206020')
with cte as (
select left(documentno,13) lpart,
regexp_replace(split_part(documentno, '/', 3), '[^0-9]', '', 'g')::int as num
from c_order
), minmax as (
select lpart, min(num) minpart, max(num) maxpart
from cte
group by lpart
)
select lpart||t.doc_no as missing_doc_no
from minmax m
cross join generate_series(minpart, maxpart) as t(doc_no)
where not exists (select *
from c_order c
where regexp_replace(split_part(c.documentno, '/', 3), '[^0-9]', '', 'g')::int = t.doc_no)
我的 fiddle : https://dbfiddle.uk/?rdbms=postgres_12&fiddle=0d3a6a647c6ef2a9063c7f3289446998
我该怎么做?
我没有写完整的解决方案,因为你已经做对了,但这里是如何使用正则表达式动态获取最后一个数字部分的方法:
select
substring(documentno, '\w*\/\d*\/') constantpart ,
max(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Maxnumericpart,
min(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Minnumericpart
from c_order co
group by constantpart
好的,这里是完整的解决方案:
select tt.constantpart || LPAD(t.doc_no::text,ll,'0') missingdocumentNo
from
(select
substring(documentno, '\w*\/\d*\/') constantpart ,
max(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Maxnumericpart,
min(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))::int Minnumericpart,
length(min(substring(regexp_replace(documentno, '\w*\/\d*\/', '') from '\d*'))) ll
from c_order co
group by constantpart
) tt
cross join generate_series(Minnumericpart, Maxnumericpart) as t(doc_no)
where not exists (
select 1
from c_order co2
where substring(co2.documentno, '\w*\/\d*\/\d*') = tt.constantpart || LPAD(t.doc_no::text,ll,'0')
)
order by missingdocumentNo;
db<>fiddle here