Skip to Main Content
  • Questions
  • Kindly help me to write a query for the above requirement.

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, SOmadatta.

Asked: December 22, 2015 - 4:31 am UTC

Last updated: December 22, 2015 - 11:29 am UTC

Version: 11

Viewed 1000+ times

You Asked

Hi All,

Please help me to write a query which will give the result with below format

Point Seq depo
XYZ 1 10
1 2 10
2 3 10
A001 4 10
A001 5 10
V308 6 10
SKDC 99 10
XYZ 99 10

ABC 1 20
83 2 20
33 3 20
B001 4 20
C001 6 20
DDoo1 99 20
ABC 99 20

OutPut
-------------------
Depp No. of Point
10 6
20 5

* get the number of point for each depo where the the point name should not be consider with respect to seq is "1"

Example:

Depo 10 have 8 records. wherein, Point are XYZ where seq=1,
then, we should exclude the XYZ records(2 records) in the count
Hence depo 10 have 6 records.


Kindly help me to write a query for the above requirement.

and Connor said...


SQL> drop table T purge;

Table dropped.

SQL>
SQL> create table T ( p varchar2(10), seq int, depo int );

Table created.

SQL>
SQL> insert into T values ('XYZ', 1 ,10);

1 row created.

SQL>
SQL> insert into T values ('1', 2, 10);

1 row created.

SQL> insert into T values ('2', 3, 10);

1 row created.

SQL> insert into T values ('A001', 4, 10);

1 row created.

SQL> insert into T values ('A001', 5, 10);

1 row created.

SQL> insert into T values ('V308', 6, 10);

1 row created.

SQL> insert into T values ('SKDC', 99, 10);

1 row created.

SQL> insert into T values ('XYZ', 99, 10);

1 row created.

SQL>
SQL>
SQL>
SQL> insert into T values ('ABC', 1 ,20);

1 row created.

SQL> insert into T values ('83',2 ,20);

1 row created.

SQL> insert into T values ('33', 3, 20);

1 row created.

SQL> insert into T values ('B001', 4 ,20);

1 row created.

SQL> insert into T values ('C001', 6 ,20);

1 row created.

SQL> insert into T values ('DDoo1', 99, 20);

1 row created.

SQL> insert into T values ('ABC', 99, 20);

1 row created.

SQL>
SQL> select depo, count(*)
  2  from T t1
  3  where not exists
  4    ( select 1 from t t2
  5      where t2.depo = t1.depo
  6      and   t2.p = t1.p
  7      and   t2.seq = 1  )
  8  group by depo
  9  order by 1;

      DEPO   COUNT(*)
---------- ----------
        10          6
        20          5

SQL>
SQL>


Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Excellent

SOmadatta Mallick, December 22, 2015 - 6:11 am UTC

Excellent!!!

This is very usefull for me. Thanks a lot Connor McDonald for swift response.

using 12c

Rajeshwaran, Jeyabal, December 22, 2015 - 6:46 am UTC

Connor,

I was able to achieve this using Analytics.

rajesh@ORA10G> select depo,count(grp)
  2  from (
  3  select depo,seq,point,
  4    case when point <> max(case when seq=1
  5        then point end) over(partition by depo
  6      order by seq) then 1 end grp
  7  from t
  8       )
  9  group by depo
 10  /

      DEPO COUNT(GRP)
---------- ----------
        10          6
        20          5

2 rows selected.

rajesh@ORA10G>


thought of playing this on Oracle 12c using SQL Pattern matching, Able to get upto this.

drop table t purge;
create table t(point varchar2(10),seq int,depo int);
insert into t values('XYZ',1,10);
insert into t values('1',2,10);
insert into t values('2',3,10); 
insert into t values('A001',4,10);
insert into t values('A001',5,10); 
insert into t values('V308',6,10); 
insert into t values('SKDC',99,10);
insert into t values('XYZ',99,10); 
insert into t values('ABC',1,20);
insert into t values('83',2,20); 
insert into t values('33',3,20); 
insert into t values('B001',4,20); 
insert into t values('C001',6,20); 
insert into t values('DDoo1',99,20); 
insert into t values('ABC',99,20); 
commit;

rajesh@ORA12C> select *
  2  from t
  3  match_recognize(
  4    partition by depo
  5    order by seq
  6    measures
  7      match_number() as mno,
  8      classifier() as classif,
  9      strt.point as x   ,
 10      down.point as y
 11      all rows per match
 12    pattern( strt down+)
 13    define
 14      strt as seq=1 ,
 15      down as prev(seq) <= down.seq )
 16  /

      DEPO        SEQ        MNO CLASS X          Y          POINT
---------- ---------- ---------- ----- ---------- ---------- ----------
        10          1          1 STRT  XYZ                   XYZ
        10          2          1 DOWN  XYZ        1          1
        10          3          1 DOWN  XYZ        2          2
        10          4          1 DOWN  XYZ        A001       A001
        10          5          1 DOWN  XYZ        A001       A001
        10          6          1 DOWN  XYZ        V308       V308
        10         99          1 DOWN  XYZ        SKDC       SKDC
        10         99          1 DOWN  XYZ        XYZ        XYZ
        20          1          1 STRT  ABC                   ABC
        20          2          1 DOWN  ABC        83         83
        20          3          1 DOWN  ABC        33         33
        20          4          1 DOWN  ABC        B001       B001
        20          6          1 DOWN  ABC        C001       C001
        20         99          1 DOWN  ABC        DDoo1      DDoo1
        20         99          1 DOWN  ABC        ABC        ABC

15 rows selected.


but when added up the CASE statement, it ended up with this error. look like Aggregates cannot be defined on two different row pattern variables( strt, down). but when defined on either single row pattern variable / universal row pattern variable this error doesn't show up.

could you help me to solve this using 12c sql pattern matching?

rajesh@ORA12C> select *
  2  from t
  3  match_recognize(
  4    partition by depo
  5    order by seq
  6    measures
  7      count(case when strt.point <>
  8          down.point then 1 end) cnt
  9      one row per match
 10    pattern( strt down+)
 11    define
 12      strt as seq=1 ,
 13      down as prev(seq) <= down.seq )
 14  /
    count(case when strt.point <>
                               *
ERROR at line 7:
ORA-62508: illegal use of aggregates or navigation operators in MATCH_RECOGNIZE clause


rajesh@ORA12C>

using 12c

Rajeshwaran, Jeyabal, December 22, 2015 - 11:01 am UTC

Team - Never mind, i am able to get that now.

rajesh@ORA12C> select *
  2     from t
  3     match_recognize(
  4       partition by depo
  5       order by seq
  6       measures
  7         count(down.*) as cnt
  8         one row per match
  9       pattern( strt down+)
 10       define
 11         strt as seq=1 ,
 12         down as prev(seq) <= down.seq
 13          and strt.point <> down.point )
 14  /

      DEPO        CNT
---------- ----------
        10          6
        20          5

2 rows selected.

rajesh@ORA12C>

Connor McDonald
December 22, 2015 - 11:29 am UTC

nice work

oops !

Rajeshwaran, Jeyabal, December 22, 2015 - 11:33 am UTC

I missed a point, if the data changes like this, the above code doesn't work.

rajesh@ORA12C> select * from t;

POINT             SEQ       DEPO
---------- ---------- ----------
XYZ                 1         10
1                   2         10
2                   3         10
A001                4         10
XYZ                 5         10
V308                6         10
SKDC               99         10
A001               99         10
ABC                 1         20
83                  2         20
33                  3         20
B001                4         20
C001                6         20
DDoo1              99         20
ABC                99         20

15 rows selected.

rajesh@ORA12C> select *
  2    from t
  3    match_recognize(
  4      partition by depo
  5      order by seq
  6      measures
  7        count(down.*) as cnt
  8        one row per match
  9      pattern( strt down+)
 10      define
 11        strt as seq=1 ,
 12        down as prev(seq) <= down.seq
 13         and strt.point <> down.point )
 14  /

      DEPO        CNT
---------- ----------
        10          3
        20          5

2 rows selected.

rajesh@ORA12C>


Instead the code should be like this

rajesh@ORA12C> select depo,cnt
  2  from  t
  3  match_recognize(
  4    partition by depo
  5    order by seq
  6    measures
  7      match_number() mno,
  8      classifier() as classif,
  9      count(x.*) cnt
 10    one row per match
 11    pattern (strt (x|down)* )
 12    define
 13      down as prev(seq) <= down.seq ,
 14      x as strt.point <> point )
 15  /

      DEPO        CNT
---------- ----------
        10          6
        20          5

2 rows selected.


sorry- keep doing more mistakes with pattern matching.