Avoid UNION ALL [message #661693] |
Tue, 28 March 2017 06:04 |
pointers
Messages: 451 Registered: May 2008
|
Senior Member |
|
|
Hi,
I have a table T_SHIPMENT, we would like to get the MAX(rfrl_strt_dt) for SPP_ID IN (100,200) and
for other SPP_IDs I would like to get all the rfrl_strt_dt.
create table t_shipment (spp_id number, rfrl_strt_dt date);
begin
insert into t_shipment values (100, sysdate-356);
insert into t_shipment values (100, sysdate-350);
insert into t_shipment values (100, sysdate-200);
insert into t_shipment values (100, sysdate-100);
--
insert into t_shipment values (200, sysdate-356);
insert into t_shipment values (200, sysdate-150);
insert into t_shipment values (200, sysdate-100);
insert into t_shipment values (200, sysdate-2);
--
insert into t_shipment values (300, sysdate-1);
insert into t_shipment values (300, sysdate-10);
insert into t_shipment values (300, sysdate-15);
insert into t_shipment values (300, sysdate-20);
--
insert into t_shipment values (400, sysdate-2);
insert into t_shipment values (400, sysdate-6);
insert into t_shipment values (400, sysdate-4);
insert into t_shipment values (400, sysdate-3);
end;
/
commit;
I could achive it using UNION ALL
SELECT spp_id, MAX (rfrl_strt_dt) rfrl_strt_dt
FROM t_shipment
WHERE spp_id IN (100, 200)
GROUP BY spp_id
--
UNION ALL
--
SELECT spp_id, rfrl_strt_dt FROM t_shipment WHERE spp_id NOT IN (100, 200);
I see the table is accessed twice, could we achieve this using a single table, I tried to do it using analytics without luck.
Thank you in advance.
Regards,
Poiners
|
|
|
Re: Avoid UNION ALL [message #661694 is a reply to message #661693] |
Tue, 28 March 2017 06:33 |
cookiemonster
Messages: 13920 Registered: September 2008 Location: Rainy Manchester
|
Senior Member |
|
|
You need to use row_number to skip the rows for 100,200 you're not interested and case to determine whether to use max or the raw data:
SQL> select spp_id, case when spp_id in (100,200) then maxt else rfrl_strt_dt end as rfrl_strt_dt
2 from (
3 select spp_id, max(rfrl_strt_dt) over (partition by spp_id) as maxt,
4 rfrl_strt_dt, row_number() over(partition by spp_id order by rfrl_strt_dt) as rn
5 from t_shipment)
6 where spp_id not in (100,200) or rn = 1;
SPP_ID RFRL_STRT_DT
---------- ------------
100 12/18/2016 1
200 03/26/2017 1
300 03/08/2017 1
300 03/13/2017 1
300 03/18/2017 1
300 03/27/2017 1
400 03/22/2017 1
400 03/24/2017 1
400 03/25/2017 1
400 03/26/2017 1
10 rows selected
|
|
|
Re: Avoid UNION ALL [message #661702 is a reply to message #661693] |
Tue, 28 March 2017 12:58 |
Solomon Yakobson
Messages: 3273 Registered: January 2010 Location: Connecticut, USA
|
Senior Member |
|
|
Just for fun - grouping sets solution:
select spp_id,
case grouping(rfrl_strt_dt)
when 0 then rfrl_strt_dt
else max( rfrl_strt_dt)
end rfrl_strt_dt
from t_shipment
group by grouping sets((spp_id),(spp_id,rfrl_strt_dt,rowid))
having grouping(rfrl_strt_dt) = case
when spp_id in (100,200) then 1
else 0
end
/
SPP_ID RFRL_STRT
---------- ---------
100 18-DEC-16
200 26-MAR-17
300 08-MAR-17
300 13-MAR-17
300 18-MAR-17
300 27-MAR-17
400 22-MAR-17
400 24-MAR-17
400 25-MAR-17
400 26-MAR-17
10 rows selected.
SQL>
SY.
|
|
|
|
|
|