How to find values missing from a sequence?

All we need is an easy explanation of the problem, so here it is.

I want to find rows missing from a sequence of values in my table. For example, in this picture documentno 'YD4BC2006008' is missing.

I want to find the missing lines via c_order_id and documentno.

I tried this but it didn’t return the expected result:

select * from
(SELECT distinct c_order_id, documentno,cast(right(documentno,3) as integer) as no
FROM adempiere.c_order
ORDER BY documentno, c_order_id) as f

How to find values missing from a sequence?

In this example many rows missing: from 'DGPOS2003030' to 'DGPOS2003068'.

How do I write a query to retrieve them?

How to find values missing from a sequence?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

A more dynamic approach would be
, getting the lowest Number and the highest and building the m missing from there.

If you don’t have a leading 2 like in the example 2006004 you need to pad the generated part

CREATE TABLE documents (
  "order_id" VARCHAR(22),
  "documentno" VARCHAR(12)
);

INSERT INTO documents
  ("order_id", "documentno")
VALUES
  ('100001110', 'VD4BC2006004'),
  ('100001114' ,'VD4BC2006005'),
  ('100001135' ,'YD4BC2006006'),
  ('100001166' ,'YD4BC2006007'),
  ('100001215' ,'YD4BC2006009'),
  ('100001256' ,'YD4BC2006010'),
  ('100001289' ,'YD4BC2006011'),
  ('100001332' ,'VD4BC2006013'),
  ('100001334' ,'VD4BC2006014'),
  ('100001432' ,'VD4BC2006015'),
  ('100000616' ,'DGP0S2003028'),
  ('100000617' ,'DGP0S2003029'),
  ('100001034' ,'DGP0S2003069');
WITH cte as (
SELECT LEFT("documentno",5) lpart , MIN(RIGHT("documentno",7)) minpart, MaX(RIGHT("documentno",7)) maxpart FROM documents
groUP BY LEFT("documentno",5))
sELECT lpart || generate_series(minpart::INTEGER, maxpart::INTEGER) as mdocumentno FROM cte
except
select documentno from documents
ORDER bY mdocumentno;
| mdocumentno  |
| :----------- |
| DGP0S2003030 |
| DGP0S2003031 |
| DGP0S2003032 |
| DGP0S2003033 |
| DGP0S2003034 |
| DGP0S2003035 |
| DGP0S2003036 |
| DGP0S2003037 |
| DGP0S2003038 |
| DGP0S2003039 |
| DGP0S2003040 |
| DGP0S2003041 |
| DGP0S2003042 |
| DGP0S2003043 |
| DGP0S2003044 |
| DGP0S2003045 |
| DGP0S2003046 |
| DGP0S2003047 |
| DGP0S2003048 |
| DGP0S2003049 |
| DGP0S2003050 |
| DGP0S2003051 |
| DGP0S2003052 |
| DGP0S2003053 |
| DGP0S2003054 |
| DGP0S2003055 |
| DGP0S2003056 |
| DGP0S2003057 |
| DGP0S2003058 |
| DGP0S2003059 |
| DGP0S2003060 |
| DGP0S2003061 |
| DGP0S2003062 |
| DGP0S2003063 |
| DGP0S2003064 |
| DGP0S2003065 |
| DGP0S2003066 |
| DGP0S2003067 |
| DGP0S2003068 |
| VD4BC2006006 |
| VD4BC2006007 |
| VD4BC2006008 |
| VD4BC2006009 |
| VD4BC2006010 |
| VD4BC2006011 |
| VD4BC2006012 |
| YD4BC2006008 |

db<>fiddle here

Method 2

One easy way is to generate a list of all potential documentnos and remove from that all the ones that exist:

select 'YD4BC' || generate_series(2006004, 2006015) as missing_documentno
except
select documentno from documents;

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply