Avatar of techlearn
techlearn
 asked on

Oracle SQL Query help

Experts,
Need some help with query.

Order table:
OrderNo, ItemNo, ItemStatus
1234 , 56566,  Sent
1234,  44545,  Hold
1234,  67888,  Processing

4567 , 65656, Sent
4567 , 45466, Hold

4566,  34566, Hold

Transaction Table:
Order No, Item No, Sub Item no, SubitemStatus
1234 ,        56566,  5656601, Sent
1234 ,        56566,  5656602, Sent
1234 ,         44545,  4454501, Sent
1234 ,         44545,   4454502, Sent
1234,          67888,  6788801, Sent

4567 , 65656, 6565601 Hold
4567 , 45466, 4546601 Sent
4567 , 45466, 4546602 Processing

4566,  34566, 3456601 Sent
4566,  34566, 3456602 Sent

Basically, i want to return only the records for the SubitemsStatus= "Sent" each record for the Order should be Sent status, if one record is 'sent' and other is 'Processing' 'hold' etc. than exclude the entire order no. For the above table. My result set should return..
 Order No, 1234 and 4566. Order 4567 should not be returned as one of the record Status is 'Hold'  and 'processing'.  

Thanks in advance.
Oracle DatabaseSQL

Avatar of undefined
Last Comment
techlearn

8/22/2022 - Mon
PortletPaul

SELECT
    *
FROM orders
INNER JOIN (
            SELECT
                Order_No
            FROM transactions
            GROUP BY
                Order_No
            HAVING MIN(SubitemStatus) = MAX(SubitemStatus)
            AND MAX(SubitemStatus) = 'Sent'
        ) all_sent ON orders.Order_No = all_sent.Order_No
;

Open in new window


Using a GROUP BY and HAVING clause will allow you to find only those where all are sent.

You haven't specified what the "expected result" should look like so I have just assumed you want rows from the orders table.

details:
    CREATE TABLE Orders
        (ORDERNO int, ITEMNO int, ITEMSTATUS varchar2(10))
    ;
    
    INSERT ALL 
        INTO Orders (ORDERNO, ITEMNO, ITEMSTATUS)
             VALUES (1234, 56566, 'Sent')
        INTO Orders (ORDERNO, ITEMNO, ITEMSTATUS)
             VALUES (1234, 44545, 'Hold')
        INTO Orders (ORDERNO, ITEMNO, ITEMSTATUS)
             VALUES (1234, 67888, 'Processing')
        INTO Orders (ORDERNO, ITEMNO, ITEMSTATUS)
             VALUES (4567, 65656, 'Sent')
        INTO Orders (ORDERNO, ITEMNO, ITEMSTATUS)
             VALUES (4567, 45466, 'Hold')
        INTO Orders (ORDERNO, ITEMNO, ITEMSTATUS)
             VALUES (4566, 34566, 'Hold')
    SELECT * FROM dual
    ;
    
    CREATE TABLE Transactions
        (ORDERNO int, ITEMNO int, SUBITEMNO int, SUBITEMSTATUS varchar2(10))
    ;
    
    INSERT ALL 
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (1234, 56566, 5656601, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (1234, 56566, 5656602, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (1234, 44545, 4454501, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (1234, 44545, 4454502, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (1234, 67888, 6788801, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (4567, 65656, 6565601, 'Hold')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (4567, 45466, 4546601, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (4567, 45466, 4546602, 'Processing')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (4566, 34566, 3456601, 'Sent')
        INTO Transactions (ORDERNO, ITEMNO, SUBITEMNO, SUBITEMSTATUS)
             VALUES (4566, 34566, 3456602, 'Sent')
    SELECT * FROM dual
    ;
    
**Query 1**:

    SELECT
        *
    FROM orders
    INNER JOIN (
                SELECT
                    OrderNo
                FROM transactions
                GROUP BY
                    OrderNo
                HAVING MIN(SubitemStatus) = MAX(SubitemStatus)
                AND MAX(SubitemStatus) = 'Sent'
            ) all_sent ON orders.OrderNo = all_sent.OrderNo

**[Results][2]**:
    | ORDERNO | ITEMNO | ITEMSTATUS | ORDERNO |
    |---------|--------|------------|---------|
    |    1234 |  67888 | Processing |    1234 |
    |    1234 |  44545 |       Hold |    1234 |
    |    1234 |  56566 |       Sent |    1234 |
    |    4566 |  34566 |       Hold |    4566 |

  [1]: http://sqlfiddle.com/#!4/f3b1b/2
  [2]: http://sqlfiddle.com/#!4/f3b1b/2/0

Open in new window

Mark Geerlings

Or in traditional Oracle SQL syntax:
select * from orders o
where (o.order_no, o.itemno) in (select t.order_no,t. item_no, max(t.subitemstatus)
  from transaction_table t
  where t.subitemstatus = 'Sent'
  group by t.order_no,t. item_no);

If your Oracle database version is 11 or higher, you can use either ANSI-standard or traditional Oracle join syntax.  I would suggest trying them both to see if one approach or the other works faster in your system.
techlearn

ASKER
Thanks Paul. Query in not working as it should be. It's showing sent as well as hold records. Can you please check once?


Markgeer: I tried you query too. Throwing this error.
ORA 00913 Too many values.
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
techlearn

ASKER
Please help. What should be done?
PortletPaul

This is what my previous query returns the following:
| ORDERNO | ITEMNO | ITEMSTATUS | ORDERNO |
|---------|--------|------------|---------|
|    1234 |  56566 |       Sent |    1234 |
|    1234 |  44545 |       Hold |    1234 |
|    1234 |  67888 | Processing |    1234 |
|    4566 |  34566 |       Hold |    4566 |

Open in new window


And that result meets this requirement:
               "Order 4567 should not be returned as one of the record Status is 'Hold'  and 'processing'.  "

but:
          >>" Query in not working as it should be. "

The trouble is you haven't really shown us what the correct result should be.

Please, using only the sample data you already provided, exactly what output are you expecting from the query?
techlearn

ASKER
Hi Maxwell,
Sorry, I apologize. The above result set is good. I missed some important info. In Transaction table we can have records with other status as well.  Please see below.

Transaction Table:
Order No, Item No, Sub Item no, SubitemStatus
1234 ,        56566,  5656601, Sent
1234 ,        56566,  5656602, Sent
1234 ,         44545,  4454501, Sent
1234 ,         44545,   4454502, Sent
A1234,          67888,  6788801, Hold

4567 , 65656, 6565601 Hold
4567 , 45466, 4546601 Sent
4567 , 45466, 4546602 Processing

4566,  34566, 3456601 Sent
A4566,  34566, 3456602 Processing

In the above table I have added A as a prefix in Order no 1234 and Order no 4566.

The result set still should be the same...
| ORDERNO | ITEMNO | ITEMSTATUS | ORDERNO |
|---------|--------|------------|---------|
|    1234 |  56566 |       Sent |    1234 |
|    1234 |  44545 |       Hold |    1234 |
|    1234 |  67888 | Processing |    1234 |
|    4566 |  34566 |       Hold |    4566 |
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
PortletPaul

I do not currently see how that added data make any difference to outcome.

1234 transactions are all = 'sent', so order 1234 is included

4566 transactions are all ='sent', so order 4566 is included

orders A1234, A4566 and 4567 do not have all transactions as 'sent', so they are excluded.

------------ BUT
Are you also trying to indicate that order 'A1234' should in some way be linked to order '1234'?
 and that order 'A4566' is related to '4566'?

If this is true then NONE of the orders have ALL transactions = 'sent' and therefore NONE would be returned.

So. bottom line, I am confused by the new information.
techlearn

ASKER
Sorry, Max. Made a mistake again.. I apologize. Please see the change now. I expect the same result set as before.  In transaction table Item No. can be null and Sub Item no can start with prefix A. This kind of record should be excluded. Again, i am sorry for the earlier confusion.

Transaction Table:
Order No, Item No, Sub Item no, SubitemStatus
1234 ,        56566,  5656601, Sent
1234 ,        56566,  5656602, Sent
1234 ,         44545,  4454501, Sent
1234 ,         44545,   4454502, Sent
1234,           Null,    A6788801, Hold
1234,           Null,    A4566866, Hold

4567 , 65656, 6565601 Hold
4567 , 45466, 4546601 Sent
4567 , 45466, 4546602 Processing

4566,  34566, 3456601 Sent
4566,  Null,  A3456602 Processing


==================
| ORDERNO | ITEMNO | ITEMSTATUS | ORDERNO |
|---------|--------|------------|---------|
|    1234 |  56566 |       Sent |    1234 |
|    1234 |  44545 |       Hold |    1234 |
|    1234 |  67888 | Processing |    1234 |
|    4566 |  34566 |       Hold |    4566 |
PortletPaul

then exclude them using a where clause ....

SELECT
    *
FROM orders
INNER JOIN (
            SELECT
                Order_No
            FROM transactions
            WHERE Item_No IS NOT NULL
            GROUP BY
                Order_No
            HAVING MIN(SubitemStatus) = MAX(SubitemStatus)
            AND MAX(SubitemStatus) = 'Sent'
        ) all_sent ON orders.Order_No = all_sent.Order_No
;

Open in new window


 WHERE Item_No IS NOT NULL appears to cover both conditions, if not add

AND NOT Item_No LIKE 'A%'

but don't add it if is not needed
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
Mark Geerlings

Or, to fix up my earlier suggestion add one word, like this:

select * from orders o
 where (o.order_no, o.itemno, 'Sent') in (select t.order_no,t. item_no, max(t.subitemstatus)
   from transaction_table t
   where t.subitemstatus = 'Sent'
   group by t.order_no,t. item_no);
techlearn

ASKER
Max,
Thanks it works, but the only problem i am seeing is. Its pulling all the records from Orders table where ItemStatus is Sent, Processing, Hold. I don't want to see the orders for which all the ItemNo Status is Sent and all Transactions Status for respective order no are Sent.  See the Sample below. 4355 should not be displayed.


Order table:
OrderNo, ItemNo, ItemStatus
4355 ,  35643,  Sent
4355 ,   35643,  Sent
4355 ,    35643,  Sent

Transaction Table:
Order No, Item No, Sub Item no, SubitemStatus
4355 ,  35643,  9956601, Sent
4355 ,   35643,  9956602, Sent
4355 ,    35643,  9954501, Sent
PortletPaul

SELECT
     ORDERNO, ITEMNO, ITEMSTATUS
FROM (
      SELECT
            o.ORDERNO, o.ITEMNO, o.ITEMSTATUS
          , MIN(o.ITEMSTATUS) OVER(PARTITION BY o.ORDERNO) AS MINSTATUS
          , MAX(o.ITEMSTATUS) OVER(PARTITION BY o.ORDERNO) AS MAXSTATUS
      FROM orders o
      INNER JOIN (
                  SELECT
                      OrderNo
                  FROM transactions
                  GROUP BY
                      OrderNo
                  HAVING MIN(SubitemStatus) = MAX(SubitemStatus)
                  AND MAX(SubitemStatus) = 'Sent'
              ) all_sent ON o.OrderNo = all_sent.OrderNo
      ) ALL_O
WHERE NOT (MINSTATUS = 'Sent' AND MAXSTATUS = 'Sent')
;

Open in new window


are all the requirements known now?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
techlearn

ASKER
Hi Max, Thanks.
When i run the above query, I do not get the below results.

Is it accounting for all the rules i have given above. Like one of them was (WHERE Item_No IS NOT NULL) in Transactions table.


| ORDERNO | ITEMNO | ITEMSTATUS | ORDERNO |
|---------|--------|------------|---------|
|    1234 |  56566 |       Sent |    1234 |
|    1234 |  44545 |       Hold |    1234 |
|    1234 |  67888 | Processing |    1234 |
|    4566 |  34566 |       Hold |    4566 |
PortletPaul

I'm sorry is that result showing above NOT what you get? if so, what DO you get instead?
ASKER CERTIFIED SOLUTION
PortletPaul

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
techlearn

ASKER
Sorry, for the delayed response.. I was not able to login to the forum lately. Thanks for your help.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes