问题
I have the following N:N table (which stores the people boardings) in my Oracle Database (it is about an airport):
CREATE TABLE boardings(
Passport VARCHAR2(8),
Day DATE,
Flight VARCHAR2(8),
LuggageWeight NUMBER(4,2),
CONSTRAINT pk PRIMARY KEY(Passport, Day, Flight));
And I would like to make a query in order to see for each flight, which has been the day that has transported the highest amount of weight (keep in mind that a same flight, as RY-1234-VY for example, can make different travels in different days. I have been trying something like this, but it doesn't work:
SELECT Day, Flight
FROM test
GROUP BY Day, Flight
HAVING SUM(LuggageWeight) = (SELECT MAX(SUM(LuggageWeight))
FROM test
GROUP BY Day, Flight);
回答1:
I think you were close.
SELECT Day, Flight
FROM boardings b1
GROUP BY Day, Flight
HAVING SUM(LuggageWeight) = (SELECT MAX(SUM(LuggageWeight))
FROM boardings b2
where b1.Flight = b2.Flight -- I have added this line
GROUP BY day, flight);
Here is a demo
Something like this? :
SELECT Flight, Day
FROM boardings b1
where (Flight, Day) = (SELECT Flight, Day
FROM boardings b2
where b2.flight = b1.flight
GROUP BY Flight, Day
order by SUM(LuggageWeight) desc
fetch first 1 rows only)
回答2:
There are several ways to approach this.
You can run the aggregation once in a common table expression and use that in a sub-query.
with totals as (
SELECT Day, Flight, SUM(LuggageWeight) total_weight
FROM test
GROUP BY Day, Flight
)
select *
from totals
where total_weight = (select max(total_weight) from totals);
Or combine the grouping with window functions:
select day, flight, total_weight
from (
SELECT Day, Flight,
SUM(LuggageWeight) total_weight,
dense_rank() over (order by SUM(LuggageWeight) desc) as rnk
FROM test
GROUP BY Day, Flight
) totals
where rnk = 1;
The above can easily be extended to also include the 2nd heaviest flight and so on. The derived table (sub-query) totals
is essentially only necessary because of visibility rules.
And if you are only interested in a single row, even if there is more than one day/flight combinations with the same (highest) total weight, you can use:
SELECT Day, Flight, SUM(LuggageWeight) total_weight
FROM test
GROUP BY Day, Flight
order by SUM(LuggageWeight) desc
fetch first 1 rows only;
Again: the above is not exactly the same as the other solutions, but might be good enough.
回答3:
I'd break this problem into two mental steps. First, you need to sum the weight per flight per day, which can be done by calling sum
in a query grouped by the flight and date. Then, for each flight, you need to find the top day, which can be done with the rank
window function:
SELECT day, flight, sum_weight
FROM (SELECT day, flight, sum_weight,
RANK() OVER (PARTITION BY flight ORDER BY sum_weight DESC) AS rk
FROM (SELECT day, flight, SUM(LuggageWeight) AS sum_weight
FROM boardings
GROUP BY day, flight) t1
) t2
WHERE rk = 1
回答4:
And I would like to make a query in order to see for each flight, which has been the day that has transported the highest amount of weight (keep in mind that a same flight, as RY-1234-VY for example, can make different travels in different days.
One solution uses window functions:
SELECT b.*
FROM (SELECT Day, Flight, SUM(LuggageWeight) as TotalWeight,
RANK() OVER (PARTITION BY Flight ORDER BY SUM(LuggageWeight) DESC) a seqnum
FROM boardings b
GROUP BY Day, Flight
) b
WHERE seqnum = 1
One solution uses two levels of aggregation:
SELECT Flight, MAX(TotalWeight),
MAX(Day) KEEP (DENSE_RANK FIRST ORDER BY TotalWeight DESC) as Day
FROM (SELECT Day, Flight, SUM(LuggageWeight) as TotalWeight,
RANK() OVER (PARTITION BY Flight ORDER BY SUM(LuggageWeight) DESC) a seqnum
FROM boardings b
GROUP BY Day, Flight
) b
GROUP BY flight;
来源:https://stackoverflow.com/questions/60681353/query-to-see-the-max-value-in-oracle