Home » SQL & PL/SQL » SQL & PL/SQL » Determine Missing Route_Seq Numbers (Oracle 11g)
Determine Missing Route_Seq Numbers [message #647343] Tue, 26 January 2016 19:30 Go to next message
stun66
Messages: 3
Registered: November 2015
Location: Dallas
Junior Member
I'm trying to determine all routes that has a missing number in the ROUTE_SEQ. For example, the query would return the ROUTE_ID=123 and ROUTE_SEQ=2 and also ROUTE_ID=456 and ROUTE_SEQ=3 from the below table. I started a query to determine the min and max but am unsure how to determine the missing ROUTE_SEQ between the min and max.

ROUTE_ID | ROUTE_SEQ
123      | 1
123      | 3
456      | 1
456      | 2
456      | 4
789      | 1
789      | 2



SELECT Min(route_seq), 
       Max(route_seq), 
       Max(route_id) 
FROM   route 
GROUP  BY route_id
Re: Determine Missing Route_Seq Numbers [message #647345 is a reply to message #647343] Tue, 26 January 2016 21:02 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9088
Registered: November 2002
Location: California, USA
Senior Member
The following determines all possible sequences between the min and max and subtracts the existing ones from that to determine the missing ones. There may be a better way, but this is the first thing that came to my mind.

SCOTT@orcl> CREATE TABLE route
  2    (route_id   NUMBER,
  3  	route_seq  NUMBER)
  4  /

Table created.

SCOTT@orcl> INSERT ALL
  2  INTO route VALUES (123, 1 )
  3  INTO route VALUES (123, 3 )
  4  INTO route VALUES (456, 1 )
  5  INTO route VALUES (456, 2 )
  6  INTO route VALUES (456, 4 )
  7  INTO route VALUES (789, 1 )
  8  INTO route VALUES (789, 2 )
  9  SELECT * FROM DUAL
 10  /

7 rows created.

SCOTT@orcl> SELECT route_id, min_seq + COLUMN_VALUE route_seq
  2  FROM   (SELECT route_id, MIN (route_seq) min_seq, MAX (route_seq) max_seq
  3  	     FROM   route
  4  	     GROUP  BY route_id),
  5  	    TABLE
  6  	      (CAST
  7  		 (MULTISET
  8  		    (SELECT LEVEL - 1
  9  		     FROM   DUAL
 10  		     CONNECT BY LEVEL <= (max_seq - min_seq + 1))
 11  	       AS SYS.ODCINUMBERLIST))
 12  MINUS
 13  SELECT route_id, route_seq
 14  FROM   route
 15  /

  ROUTE_ID  ROUTE_SEQ
---------- ----------
       123          2
       456          3

2 rows selected.

Re: Determine Missing Route_Seq Numbers [message #647354 is a reply to message #647345] Wed, 27 January 2016 01:41 Go to previous messageGo to next message
_jum
Messages: 577
Registered: February 2008
Senior Member
Here we collect all possible route_seq and compare them with them in the the different routes:

WITH rges AS
 (SELECT           CAST (COLLECT(DISTINCT route_seq) AS KU$_OBJNUMSET) rs_ges
  FROM route),
     rs AS
 (SELECT route_id, CAST (COLLECT(DISTINCT route_seq) AS KU$_OBJNUMSET) rs_part
   FROM route 
  GROUP BY route_id)
SELECT route_id, rs_ges MULTISET EXCEPT rs_part AS rs_miss
  FROM rges, rs; 



  ROUTE_ID RS_MISS(ELEMENT)
---------- ------------------
       123 KU$_OBJNUMSET(2,4)
       456 KU$_OBJNUMSET(3)  
       789 KU$_OBJNUMSET(3,4)

3 rows selected.

[Updated on: Wed, 27 January 2016 01:41]

Report message to a moderator

Re: Determine Missing Route_Seq Numbers [message #647357 is a reply to message #647354] Wed, 27 January 2016 01:55 Go to previous messageGo to next message
Michel Cadot
Messages: 68641
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

(123, 4), (789,3) are not missing, they are out of the list.
Try to do the same thing than Barbara with your method.

Re: Determine Missing Route_Seq Numbers [message #647360 is a reply to message #647357] Wed, 27 January 2016 02:43 Go to previous messageGo to next message
_jum
Messages: 577
Registered: February 2008
Senior Member
If we are only looking for missing route_seq between min and max for each route_id, then I misinterpreted the question and Barbaras solution is superior.
Re: Determine Missing Route_Seq Numbers [message #647420 is a reply to message #647345] Wed, 27 January 2016 05:55 Go to previous message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Recursive solution pin-pointed to generate just missing route sequences versus generating whole range and "minusing" existing:

with t as (
           select  route_id,
                   route_seq + 1 gap_start_route_seq,
                   lead(route_seq,1,route_seq) over(partition by route_id order by route_seq) - 1 gap_end_route_seq
             from  route
          ),
     r(
       route_id,
       route_seq,
       gap_end_route_seq
      ) as (
             select  route_id,
                     gap_start_route_seq route_seq,
                     gap_end_route_seq
               from  t
               where gap_start_route_seq <= gap_end_route_seq
            union all
             select  route_id,
                     route_seq + 1 route_seq,
                     gap_end_route_seq
               from  r
               where route_seq < gap_end_route_seq
           )
select  route_id,
        route_seq
  from  r
/

  ROUTE_ID  ROUTE_SEQ
---------- ----------
       123          2
       456          3

SQL>


Model solution if recursive subquery factoring is not available (10G):

with t as (
           select  route_id,
                   route_seq + 1 gap_start_route_seq,
                   lead(route_seq,1,route_seq) over(partition by route_id order by route_seq) - 1 gap_end_route_seq
             from  route
          )
select  route_id,
        route_seq
  from  t
  where gap_start_route_seq <= gap_end_route_seq
  model
    return updated rows
    partition by(route_id,gap_start_route_seq)
    dimension by(1 d)
    measures(gap_start_route_seq route_seq,gap_end_route_seq)
    rules(
          route_seq[for d from route_seq[1] to gap_end_route_seq[1] increment 1] = cv(d)
         )
/

  ROUTE_ID  ROUTE_SEQ
---------- ----------
       456          3
       123          2

SQL>


SY.
Previous Topic: SQL QUERY HELP
Next Topic: How to capture particular column from select statement inside a package body in oracle pl sql
Goto Forum:
  


Current Time: Thu Apr 18 19:25:10 CDT 2024