Oracle: group in one row all the data filtering by max and min
i have this data
RESERVATION PREFIX FLIGHT ORIGIN DESTINATION DATE_FLIGHT -------------------------------------------------------------- 111 LA 123 LAX MIA 2020-02-01 00:00 111 LA 122 MIA SCL 2020-02-01 10:30 111 LA 667 MIA SCL 2020-02-03 14:15 111 LA 882 SCL ARG 2020-02-03 16:00 111 LA 111 SCL ARG 2020-02-03 23:00 111 LA 966 SCL ARG 2020-02-03 23:30 111 LA 622 SCL ARG 2020-02-05 08:00
I need to filter through all the information and just leave the data of the first and last flight in one row
RESERVATION PREFIX_min FLIGHT_min ORIGIN_min DESTINATION_min DATE_FLIGHT_min PREFIX_max FLIGHT_max ORIGIN_max DESTINATION_max DATE_FLIGHT_max ------------------------------------------------------------------------------------------------------------------------------------------------------------- 111 LA 123 LAX MIA 2020-02-01 00:0 LA 622 SCL ARG 2020-02-05 08:00
You don't need any (inefficient) self-joins. Just use aggregation with KEEP DENSE_RANK FIRST|LAST
:
SELECT reservation, MIN( prefix ) KEEP ( DENSE_RANK FIRST ORDER BY date_flight ) AS prefix_min, MIN( flight ) KEEP ( DENSE_RANK FIRST ORDER BY date_flight ) AS flight_min, MIN( origin ) KEEP ( DENSE_RANK FIRST ORDER BY date_flight ) AS origin_min, MIN( destination ) KEEP ( DENSE_RANK FIRST ORDER BY date_flight ) AS desination_min, MIN( date_flight ) AS date_flight_min, MIN( prefix ) KEEP ( DENSE_RANK LAST ORDER BY date_flight ) AS prefix_max, MIN( flight ) KEEP ( DENSE_RANK LAST ORDER BY date_flight ) AS flight_max, MIN( origin ) KEEP ( DENSE_RANK LAST ORDER BY date_flight ) AS origin_max, MIN( destination ) KEEP ( DENSE_RANK LAST ORDER BY date_flight ) AS desination_max, MAX( date_flight ) AS date_flight_max FROM table_name GROUP BY reservation;
so for your test data:
create table table_name ( RESERVATION, PREFIX, FLIGHT, ORIGIN, DESTINATION, DATE_FLIGHT ) AS SELECT 111, 'LA', 123, 'LAX', 'MIA', DATE '2020-02-01' + INTERVAL '00:00' HOUR TO MINUTE FROM DUAL UNION ALL SELECT 111, 'LA', 122, 'MIA', 'SCL', DATE '2020-02-01' + INTERVAL '10:30' HOUR TO MINUTE FROM DUAL UNION ALL SELECT 111, 'LA', 667, 'MIA', 'SCL', DATE '2020-02-03' + INTERVAL '14:15' HOUR TO MINUTE FROM DUAL UNION ALL SELECT 111, 'LA', 882, 'SCL', 'ARG', DATE '2020-02-03' + INTERVAL '16:00' HOUR TO MINUTE FROM DUAL UNION ALL SELECT 111, 'LA', 111, 'SCL', 'ARG', DATE '2020-02-03' + INTERVAL '23:00' HOUR TO MINUTE FROM DUAL UNION ALL SELECT 111, 'LA', 966, 'SCL', 'ARG', DATE '2020-02-03' + INTERVAL '23:30' HOUR TO MINUTE FROM DUAL UNION ALL SELECT 111, 'LA', 622, 'SCL', 'ARG', DATE '2020-02-05' + INTERVAL '08:00' HOUR TO MINUTE FROM DUAL;
this outputs:
RESERVATION | PREFIX_MIN | FLIGHT_MIN | ORIGIN_MIN | DESINATION_MIN | DATE_FLIGHT_MIN | PREFIX_MAX | FLIGHT_MAX | ORIGIN_MAX | DESINATION_MAX | DATE_FLIGHT_MAX ----------: | :--------- | ---------: | :--------- | :------------- | :------------------ | :--------- | ---------: | :--------- | :------------- | :------------------ 111 | LA | 123 | LAX | MIA | 2020-02-01 00:00:00 | LA | 622 | SCL | ARG | 2020-02-05 08:00:00
db<>fiddle here
Having Sums, Averages, and Other Grouped Data, All aggregate functions group data to ultimately produce a single result value. The query requests a count of all rows and a count of all manager values for all employee Code Listing 9: MAX and MIN obtain maximum and minimum column values Just as a SELECT list can use a WHERE clause to filter the result set to� SQL> select ename 2 , deptno 3 , sal 4 from ( 5 select ename 6 , deptno 7 , sal 8 , max (sal) over (partition by deptno) max_sal 9 , min (sal) over (partition by deptno) min_sal 10 from emp 11 ) 12 where sal = max_sal 13 or sal = min_sal 14 order by deptno, sal 15 / ENAME DEPTNO SAL ----- ----- ----- KISHORE 10 1300 SCHNEIDER 10 5000 CLARKE 20
You can group by reservation
to get the earliest and the latest date and then join this query to 2 copies of the table:
select t.RESERVATION, t1.PREFIX PREFIX_min, t1.FLIGHT FLIGHT_min, t1.ORIGIN ORIGIN_min, t1.DESTINATION DESTINATION_min, t1.DATE_FLIGHT DATE_FLIGHT_min, t2.PREFIX PREFIX_max, t2.FLIGHT FLIGHT_max, t2.ORIGIN ORIGIN_max, t2.DESTINATION DESTINATION_max, t2.DATE_FLIGHT DATE_FLIGHT_max from ( select RESERVATION, min(DATE_FLIGHT) DATE_FLIGHT_min, max(DATE_FLIGHT) DATE_FLIGHT_max from tablename group by RESERVATION ) t inner join tablename t1 on t1.RESERVATION = t.RESERVATION AND t1.DATE_FLIGHT = t.DATE_FLIGHT_min inner join tablename t2 on t2.RESERVATION = t.RESERVATION AND t2.DATE_FLIGHT = t.DATE_FLIGHT_max
This will return 1 row for each reservation if there are no duplicate dates. See the demo. Results:
> RESERVATION | PREFIX_MIN | FLIGHT_MIN | ORIGIN_MIN | DESTINATION_MIN | DATE_FLIGHT_MIN | PREFIX_MAX | FLIGHT_MAX | ORIGIN_MAX | DESTINATION_MAX | DATE_FLIGHT_MAX > ----------: | :--------- | ---------: | :--------- | :-------------- | :--------------- | :--------- | ---------: | :--------- | :-------------- | :--------------- > 111 | LA | 123 | LAX | MIA | 2020-02-01 00:00 | LA | 622 | SCL | ARG | 2020-02-05 08:00
Tutorial: Aggregating Rows: Databases for , Aggregate Functions � Sum: the result of adding up all the values for the expression in the group � Min: the smallest value in the group � Max: the� If you omit the GROUP BY clause, then Oracle applies aggregate functions in the select list to all the rows in the queried table or view. You use aggregate functions in the HAVING clause to eliminate groups from the output based on the results of the aggregate functions, rather than on the values of the individual rows of the queried table or view.
Bit similar to @forpas but using CTE
with min_max as ( select distinct reservation, min(date_flight) over(partition by reservation) as date_flight_min, max(date_flight) over(partition by reservation) as date_flight_max from tablename ) select m.reservation, t1.prefix as prefix_min, t1.flight as flight_min, t1.origin as origin_min, t1.destination as destination_min, m.date_flight_min, t2.prefix as prefix_max, t2.flight as flight_max, t2.origin as origin_max, t2.destination as destination_max, m.date_flight_max from min_max m join tablename t1 on t1.date_flight=m.date_flight_min join tablename t2 on t2.date_flight=m.date_flight_max
Ask TOM "Howto select first value in a group by bunch of ro", How to remove the rows in a group if any one row in the group does not satisfy a condition? I was not able to filter the group if the status_id is not in 203 or 204. not sure what you mean at all. min, max, sum, avg, count do not always and with repeated data - min, max, sum are definitely NOT the same The query requests a count of all rows and a count of all manager values for all employee records with a hire date matching the current day’s system date, SYSDATE. Because no one was hired on the date the query was run, a count value of 0 is returned. Code Listing 7: COUNT(*) and COUNT(column_name) both return 0 when no rows match
Aggregate Functions, Aggregate functions return a single result row based on groups of rows, rather clause, then Oracle applies aggregate functions in the select list to all the rows in the For all the remaining aggregate functions, if the data set contains no rows, The aggregate functions MIN , MAX , SUM , AVG , COUNT , VARIANCE , and� The MIN function is one that I use quite a lot in Oracle SQL. In this article, I’ll explain how to use it, and show you some examples. Purpose of the Oracle MIN Function. The MIN function returns the minimum value of the expression you provide it. This is almost the same as the lowest value.
The MIN() and MAX() optimizations, The optimizer knows that it can avoid iterating through all the source rows in a result to compute a MIN() or MAX() aggregate when data are already in the right� CASE, GROUP BY, ROW_NUMBER, and WITH are all described in the SQL Language manual. The only one that might be tricky to find in the index is WITH. In your problem, you don't want a separate row of output for each combination of deptno and job; you want a separate row of output for every combination of col1, col2, and col3.
SELECT MIN(MyTable01.Id) as Id, MyTable01.Val as Val, MyTable01.Kind as Kind FROM MyTable MyTable01, (SELECT Val,MIN(Kind) as Kind FROM MyTable GROUP BY Val) MyTableGroup WHERE MyTable01.Val = MyTableGroup.Val AND MyTable01.Kind = MyTableGroup.Kind GROUP BY MyTable01.Val,MyTable01.Kind ORDER BY Id;
Comments
- HOw do you determine that flight 123 is the 1st flight, and not 122? They both have the same date?
- you're right , its date_flight its a time_stamp value , I will edit the post