I created a select in Oracle which returns the number of overnight stays per month (if any) for flight crew:
CRE_ALPHA CRE_NAME MONTH YEAR NIGHT_STOPS
---------- --------- ------ ----- ------------
AAC Adinda 6 2013 8
AAC Adinda 7 2013 9
AAC Adinda 8 2013 2
AAC Adinda 9 2013 7
AAC Adinda 10 2013 4
CCU Cristiano 6 2013 5
CCU Cristiano 7 2013 6
CCU Cristiano 8 2013 3
CCU Cristiano 9 2013 11
CVA Carine 7 2013 9
CVA Carine 9 2013 10
CVA Carine 10 2013 10
Now, there is a limit of 18 night stops on a 3-month basis. So I would like to group by any 3 succeeding months having > 18 night stops. The result should be something like this:
CRE_ALPHA CRE_NAME TIMESPAN NIGHT_STOPS
---------- --------- --------------- ------------
AAC Adinda 6/2013-8/2013 19
AAC Adinda 7/2013-9/2013 18
CCU Cristiano 7/2013-9/2013 20
CVA Carine 7/2013-9/2013 19
CVA Carine 8/2013-10/2013 20
Note that if there are zero night stops for a month, there is no row, but I would like a result for 3 months including the one with 0.
Can anybody help?
If it can help, the full select below:
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MM-YYYY hh24:mi:ss';
SELECT cre_id, cre_alpha, cre_first_name, cre_last_name, Maand, Jaar, count(*) "Night stops"
FROM
(SELECT cre_id, cre_alpha, cre_first_name, cre_last_name, pos_crb_iata_code, dst, det, dsa, (dst - Prev_end_time) * 1440 stop_over, EXTRACT(MONTH FROM dst) Maand, EXTRACT(YEAR FROM dst) Jaar
FROM
(SELECT cre_id, cre_alpha, cre_first_name, cre_last_name, pos_crb_iata_code, dst, dsa, det, dea, LAG(det) OVER (ORDER BY cre_alpha, dst) Prev_end_time
FROM
(SELECT cre_id, cre_alpha, cre_first_name, cre_last_name, pos_crb_iata_code,
COALESCE(flt_mvt_db, flt_com_dep_blk, pog_std, gco_start, oth_std, rsv_std) as dst,
COALESCE(flt_mvt_ab, flt_com_arr_blk, pog_sta, gco_end, oth_sta, rsv_sta) as det,
COALESCE(flt_apt_iata_code_dep, pog_apt_iata_code_from, gco_apt_iata_code, rsv_apt_iata_code) as dsa,
COALESCE(flt_apt_iata_code_arr, pog_apt_iata_code_to, gco_apt_iata_code, rsv_apt_iata_code) as dea
FROM
(SELECT DISTINCT cre_id, cre_alpha, cre_first_name, cre_last_name, pos_crb_iata_code
FROM master.crews, master.assignments, master.positions
WHERE asg_pos_id = pos_id AND asg_cre_id = cre_id AND asg_d_type <> 'LEA'
AND asg_start_time BETWEEN '01-JUN-2013' AND '01-NOV-2013'
ORDER BY cre_alpha) tab1, master.assignments
FULL OUTER JOIN master.flights ON master.assignments.asg_flt_id = master.flights.flt_id
FULL OUTER JOIN master.positionings ON master.assignments.asg_pog_id = master.positionings.pog_id
FULL OUTER JOIN master.ground_courses ON master.assignments.asg_gco_id = master.ground_courses.gco_id
FULL OUTER JOIN master.other_duties ON master.assignments.asg_oth_id = master.other_duties.oth_id
FULL OUTER JOIN master.reserves ON master.assignments.asg_rsv_id = master.reserves.rsv_id
WHERE asg_d_type <> 'LEA' AND asg_d_type <> 'STP' AND asg_cre_id = tab1.cre_id
AND asg_start_time BETWEEN '01-JUN-2013' AND '02-NOV-2013' AND asg_actif = 'Y'
ORDER BY cre_alpha, asg_start_time)
)
WHERE pos_crb_iata_code <> dsa
AND EXTRACT(DAY FROM dst) - EXTRACT(DAY FROM Prev_end_time) >= 1)
WHERE stop_over > 240
GROUP BY cre_id, cre_alpha, cre_first_name, cre_last_name, Maand, Jaar
ORDER BY cre_alpha;
You can use analytical functions to achieve what you want. Building on top of your current query, it goes like this:
select *
from (
select cre_alpha, cre_name,
month month_end, year year_end,
sum(night_stops) over (
partition by cre_alpha, cre_name
order by year * 12 + month
range between 2 preceding and current row
) as night_stops
from (
... your current query ...
) t
) m
where night_stops >= 18
Note:
>= 18
to match your output even though the text says it's > 18
.range between 2 preceding and current row
together with the order by clause year * 12 + month
make sure a three month window is taken and not just three consecutive rows. This is relevant if you have missing month in your base query.Have fun.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With