从列中读取数据并动态生成缺失行的函数

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