Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

tìm các số còn thiếu từ chuỗi sau khi nhận được chuỗi từ một chuỗi?

Bạn không muốn nhìn vào dual ở tất cả ở đây; chắc chắn không cố gắng chèn. Bạn cần theo dõi các giá trị cao nhất và thấp nhất mà bạn đã thấy khi lặp qua vòng lặp. dựa trên một số phần tử của ename thể hiện ngày tháng Tôi khá chắc rằng bạn muốn tất cả các kết quả phù hợp của mình là 0-9 , không phải 1-9 . Bạn cũng đang đề cập đến tên con trỏ khi bạn truy cập vào các trường của nó, thay vì tên biến bản ghi:

  FOR List_ENAME_rec IN List_ENAME_cur loop
    if REGEXP_LIKE(List_ENAME_rec.ENAME,'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]') then 
      V_seq := substr(List_ENAME_rec.ename,5,4);
      V_Year := substr(List_ENAME_rec.ename,10,2);
      V_Month := substr(List_ENAME_rec.ename,13,2);
      V_day := substr(List_ENAME_rec.ename,16,2);

      if min_seq is null or V_seq < min_seq then
        min_seq := v_seq;
      end if;
      if max_seq is null or V_seq > max_seq then
        max_seq := v_seq;
      end if;

    end if;
  end loop;

Với các giá trị trong bảng của emp-1111_14_01_01_1111_G1emp-1115_14_02_02_1111_G1 , báo cáo max_seq 1115 min_seq 1111 .

Nếu bạn thực sự muốn liên quan đến kép, bạn có thể thực hiện điều này bên trong vòng lặp, thay vì mẫu if / then / gán, nhưng nó không cần thiết:

      select least(min_seq, v_seq), greatest(max_seq, v_seq)
      into min_seq, max_seq
      from dual;

Tôi không biết thủ tục sẽ làm gì; dường như không có mối quan hệ nào giữa những gì bạn có trong test1 và các giá trị bạn đang tìm kiếm.

Bạn không cần bất kỳ PL / SQL nào cho việc này. Bạn có thể nhận các giá trị tối thiểu / tối đa từ một truy vấn đơn giản:

select min(to_number(substr(ename, 5, 4))) as min_seq,
  max(to_number(substr(ename, 5, 4))) as max_seq
from table1
where status = 2
and regexp_like(ename,
  'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')

   MIN_SEQ    MAX_SEQ
---------- ----------
      1111       1115 

Và bạn có thể sử dụng những giá trị đó để tạo danh sách tất cả các giá trị trong phạm vi đó:

with t as (
  select min(to_number(substr(ename, 5, 4))) as min_seq,
    max(to_number(substr(ename, 5, 4))) as max_seq
  from table1
  where status = 2
  and regexp_like(ename,
    'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
)
select min_seq + level - 1 as seq
from t
connect by level <= (max_seq - min_seq) + 1;

       SEQ
----------
      1111 
      1112 
      1113 
      1114 
      1115 

Và một biểu thức bảng thông thường hơi khác để xem biểu thức nào trong số đó không tồn tại trong bảng của bạn, mà tôi nghĩ đó là những gì bạn đang theo đuổi:

with t as (
  select to_number(substr(ename, 5, 4)) as seq
  from table1
  where status = 2
  and regexp_like(ename,
    'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
),
u as (
  select min(seq) as min_seq,
    max(seq) as max_seq
  from t
),
v as (
  select min_seq + level - 1 as seq
  from u
  connect by level <= (max_seq - min_seq) + 1
)
select v.seq as missing_seq
from v
left join t on t.seq = v.seq
where t.seq is null
order by v.seq;

MISSING_SEQ
-----------
       1112 
       1113 
       1114 

hoặc nếu bạn thích:

...
select v.seq as missing_seq
from v
where not exists (select 1 from t where t.seq = v.seq)
order by v.seq;

SQL Fiddle .

Dựa trên các nhận xét, tôi nghĩ bạn muốn các giá trị còn thiếu cho chuỗi cho mỗi kết hợp của các phần tử khác của ID (YY_MM_DD). Điều này sẽ cung cấp cho bạn bảng phân tích đó:

with t as (
  select to_number(substr(ename, 5, 4)) as seq,
    substr(ename, 10, 2) as yy,
    substr(ename, 13, 2) as mm,
    substr(ename, 16, 2) as dd
  from table1
  where status = 2
  and regexp_like(ename,
    'emp[-][0-9]{4}[_][0-9]{2}[_][0-9]{2}[_][0-9]{2}[_][0-9]{4}[_][G][1]')
),
r (yy, mm, dd, seq, max_seq) as (
  select yy, mm, dd, min(seq), max(seq)
  from t
  group by yy, mm, dd
  union all
  select yy, mm, dd, seq + 1, max_seq
  from r
  where seq + 1 <= max_seq
)
select yy, mm, dd, seq as missing_seq
from r
where not exists (
  select 1 from t
  where t.yy = r.yy
  and t.mm = r.mm
  and t.dd = r.dd
  and t.seq = r.seq
)
order by yy, mm, dd, seq;

Với đầu ra như:

YY   MM   DD    MISSING_SEQ 
---- ---- ---- -------------
14   01   01            1112 
14   01   01            1113 
14   01   01            1114 
14   02   02            1118 
14   02   02            1120 
14   02   03            1127 
14   02   03            1128 

SQL Fiddle .

Nếu bạn muốn tìm một ngày cụ thể, bạn lọc lạnh (trong t hoặc nhánh đầu tiên trong r ), nhưng bạn cũng có thể thay đổi mẫu regex để bao gồm các giá trị cố định; vì vậy để tìm 14 06 mẫu sẽ là 'emp[-][0-9]{4}_14_06_[0-9]{2}[_][0-9]{4}[_][G][1]' , Ví dụ. Tuy nhiên, điều đó khó tổng quát hơn, vì vậy một bộ lọc (where t.yy = '14' and t.mm = '06' có thể linh hoạt hơn.

Nếu bạn khăng khăng muốn có điều này trong một thủ tục, bạn có thể làm cho các phần tử ngày tháng tùy chọn và sửa đổi mẫu regex:

create or replace procedure show_missing_seqs(yy in varchar2 default '[0-9]{2}',
  mm in varchar2 default '[0-9]{2}', dd in varchar2 default '[0-9]{2}') as

  pattern varchar2(80);
  cursor cur (pattern varchar2) is
    with t as (
      select to_number(substr(ename, 5, 4)) as seq,
        substr(ename, 10, 2) as yy,
        substr(ename, 13, 2) as mm,
        substr(ename, 16, 2) as dd
      from table1
      where status = 2
      and regexp_like(ename, pattern)
    ),
    r (yy, mm, dd, seq, max_seq) as (
      select yy, mm, dd, min(seq), max(seq)
      from t
      group by yy, mm, dd
      union all
      select yy, mm, dd, seq + 1, max_seq
      from r
      where seq + 1 <= max_seq
    )
    select yy, mm, dd, seq as missing_seq
    from r
    where not exists (
      select 1 from t
      where t.yy = r.yy
      and t.mm = r.mm
      and t.dd = r.dd
      and t.seq = r.seq
    )
    order by yy, mm, dd, seq;
begin
  pattern := 'emp[-][0-9]{4}[_]'
    || yy || '[_]' || mm || '[_]' || dd
    || '[_][0-9]{4}[_][G][1]';
  for rec in cur(pattern) loop
    dbms_output.put_line(to_char(rec.missing_seq, 'FM0000'));
  end loop;
end show_missing_seqs;
/

Tôi không biết tại sao bạn nhấn mạnh rằng nó phải được thực hiện như thế này hoặc tại sao bạn muốn sử dụng dbms_output khi bạn đang dựa vào máy khách / người gọi hiển thị điều đó; công việc của bạn sẽ làm gì với đầu ra? Bạn có thể đặt trả về này là sys_refcursor sẽ linh hoạt hơn. nhưng dù sao, bạn có thể gọi nó như thế này từ SQL * Plus / SQL Developer:

set serveroutput on
exec show_missing_seqs(yy => '14', mm => '01');

anonymous block completed
1112
1113
1114



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Sử dụng pivot trên nhiều cột của một hàng Oracle

  2. chạy một tệp exe trong trình kích hoạt oracle

  3. Tự động tra cứu tên cột cho một bảng trong khi truy vấn sql

  4. Tôi có thể bỏ qua xác minh chứng chỉ oracle utl_http không?

  5. Bạn có thể sử dụng các tham số được đặt tên trong Laravel Eloquent không