user13060942
user13060942

Reputation:

Take max correlated value in Oracle?

I have the following tables in my Oracle 11g database:

CREATE TABLE travels
(
Day DATE,
Flight_Code VARCHAR2(7),
Airplane_Code VARCHAR2(7),
CONSTRAINT pk PRIMARY KEY(day,flight_code)
);

and

CREATE TABLE boardings
(
Passport VARCHAR2(7),
Day DATE,
Flight_Code VARCHAR2(7),
Luggage_Weight NUMBER(4,2),
CONSTRAINT pk PRIMARY KEY(passport,day,flight_code)
);

So I am trying to make a query in order to see for each airplane which has been the flight (Day and Flight_Code) that it has transported the maximum amount of weight, being that amount always higher than 100 (keep in mind that a same flight, as RY-1234-VY for example, can make different travels in different days, but not more than one in a same day).

I have been trying something like this but it doesn't work, because it returns for each flight which has been the day that it has been transported more Luggage_Weight, and the airplane who has done it.

SELECT Airplane_Code, Day, Flight_Code
FROM Travels
WHERE (Day, Flight_Code) IN (SELECT Day, Flight_Code
                                 FROM boardings b1
                                 GROUP BY Day, Flight_Code
                                 HAVING SUM(Luggage_Weight) = (SELECT MAX(SUM(Luggage_Weight))
                                                              FROM boardings b2
                                                              WHERE b1.Flight_Code = b2.Flight_Code
                                                              GROUP BY Day, Flight_Code
                                                              HAVING SUM(Luggage_Weight) > 100))
GROUP BY Airplane_Code, Day, Flight_Code;

I would like the solution to use GROUP BY and HAVING structure.

For example:

INSERT INTO travels VALUES ('04/04/2020', 'RY1234', 'ABCD');
INSERT INTO travels VALUES ('03/04/2020', 'RY1234', 'ABCD');

INSERT INTO boardings VALUES ('ES1234', '04/04/2020', 'RY1234', '51');
INSERT INTO boardings VALUES ('ES5678', '04/04/2020', 'RY1234', '50');
INSERT INTO boardings VALUES ('ES9101', '03/04/2020', 'RY1234', '100');

As u can see, the same flight (RY1234) has travelled in 2 different days, so in 03/04, the total LuggageWeight has been 100kg, but in the 04/04, the total LuggageWeight has been 101kg. The result should be the next:

ABCD ---- 04/04/2020 ---- RY1234

In the case that it wouldn't have reached the 100kg in any of its flights for the same airplane, that airplane code should not be shown.

Upvotes: 2

Views: 107

Answers (3)

psaraj12
psaraj12

Reputation: 5072

You can use subquery refactoring along with GROUP BY and HAVING like below to get your result.

When you say the below you need to group by Flight_code alone to get the Max weight.

So I am trying to make a query in order to see for each airplane which has been the flight (Day and Flight_Code) that it has transported the maximum amount of weight, being that amount always higher than 100 (keep in mind that a same flight, as RY-1234-VY for example, can make different travels in different days, but not more than one in a same day).

            WITH t
             AS (SELECT t.airplane_code,
                        t.day,
                        t.flight_code,
                        SUM(luggage_weight) wt
                 FROM   travels t,
                        boardings b
                 WHERE  t.flight_code = b.flight_code
                        AND Trunc(t.day) = Trunc(b.day)
                 GROUP  BY t.airplane_code,
                           t.day,
                           t.flight_code
                 HAVING SUM(luggage_weight) > 100),
             t1
             AS (SELECT Max(wt) wt,
                        flight_code
                 FROM   t
                 GROUP  BY
                           flight_code)
        SELECT t.*
        FROM   t,
               t1
        WHERE  t.wt = t1.wt
               AND t.flight_code = t1.flight_code 

Without sub query refactoring you can use like the below

 SELECT t.airplane_code,
           t.day,
           t.flight_code
    FROM   travels t,
           boardings b
    WHERE  t.flight_code = b.flight_code
           AND Trunc(t.day) = Trunc(b.day)
    GROUP  BY t.airplane_code,
              t.day,
              t.flight_code
    HAVING SUM(luggage_weight) IN (SELECT Max(wt) wt
                                   FROM   (SELECT b.day,
                                                  b.flight_code,
                                                  SUM(luggage_weight) wt
                                           FROM   boardings b
                                           GROUP  BY b.day,
                                                     b.flight_code
                                           HAVING SUM(luggage_weight) > 100)rec
                                   WHERE  rec.flight_code = t.flight_code
                                   GROUP  BY t.flight_code)

you can also use something like the below

   SELECT *
    FROM   travels t
    WHERE  ( Trunc(t.day), t.flight_code ) IN (SELECT Trunc(b.day),
                                                      b.flight_code
                                               FROM   boardings b
                                               GROUP  BY b.day,
                                                         b.flight_code
                                               HAVING SUM(luggage_weight) IN
                                                      (SELECT Max(wt) wt
                                                       FROM
                                              (SELECT b.day,
                                                      b.flight_code,
                                                      SUM(luggage_weight)
                                                      wt
                                               FROM   boardings b
                                               GROUP  BY b.day,
                                                         b.flight_code
                                               HAVING SUM(luggage_weight) >
                                                      100)rec
                                                       WHERE
                  rec.flight_code = b.flight_code

Upvotes: 0

sticky bit
sticky bit

Reputation: 37482

You can use dense_rank() in a derived table to rank the flights by the sum() of their weights. Then join that to travels and filter for the rank being 1.

SELECT t.airplane_code,
       t.day,
       t.flight_code
       FROM travels t
            INNER JOIN (SELECT b.day,
                               b.flight_code,
                               dense_rank() OVER (ORDER BY sum(b.luggage_weight) DESC) dr
                               FROM boardings b
                               GROUP BY b.day,
                                        b.flight_code) x
                       ON x.day = t.day
                          AND x.flight_code = t.flight_code
            WHERE x.dr = 1;

db<>fiddle

Upvotes: 1

Mansi Raval
Mansi Raval

Reputation: 371

select Airplane_Code,day,Flight_Code from (
Select Airplane_Code,day,Flight_Code ,sum(Luggage_Weight) over (Partition by 
Flight_Code,day) as total_weight
from travels t,boardings b
where t.Flight_Code=b.Flight_Code)data1
where data1.total_weight >100;

Upvotes: 0

Related Questions