How to make raw SQL query chainable using Scope? -Rails - sql

I have written a SQL and i want this to be chainable or i can use this query as a scope in Rails? any thoughts?
select '{Critical: '||"Critical"||', Major: '||"Major"||', Moderate:
'||"Moderate"||', Minor: '||"Minor"||', Clear: '||"Clear"||'}' as result
from (
select
sum(case when max_weight=1 THEN 1 else 0 End ) as "Clear",
sum(case when max_weight=2 THEN 1 else 0 End ) as "Minor",
sum(case when max_weight=3 THEN 1 else 0 End ) as "Moderate",
sum(case when max_weight=22 THEN 1 else 0 End ) as "Major",
sum(case when max_weight=160 THEN 1 else 0 End ) as "Critical",
count(*) as number_of_answers
from (
select
fua.forms_user_id,
max(fa.weight) max_weight
from
public.forms_user_answers fua
join public.forms_users fu on (fua.forms_user_id = fu.id)
left join public.form_answers fa on (fua.form_answer_id = fa.id)
where
fu.form_id = #{form.id}
group by
fua.forms_user_id
) subq
) subq1

It's unlikely you'll be able to make that kind of query chainable with ActiveRecord. But you can certainly make a scope for the query in Rails:
scope :my_scope, -> {
self.connection.execute("
select '{Critical: '||"Critical"||', Major: '||"Major"||', Moderate:
'||"Moderate"||', Minor: '||"Minor"||', Clear: '||"Clear"||'}' as result
from (
select
sum(case when max_weight=1 THEN 1 else 0 End ) as "Clear",
sum(case when max_weight=2 THEN 1 else 0 End ) as "Minor",
sum(case when max_weight=3 THEN 1 else 0 End ) as "Moderate",
sum(case when max_weight=22 THEN 1 else 0 End ) as "Major",
sum(case when max_weight=160 THEN 1 else 0 End ) as "Critical",
count(*) as number_of_answers
from (
select
fua.forms_user_id,
max(fa.weight) max_weight
from
public.forms_user_answers fua
join public.forms_users fu on (fua.forms_user_id = fu.id)
left join public.form_answers fa on (fua.form_answer_id = fa.id)
where
fu.form_id = #{form.id}
group by
fua.forms_user_id
) subq
) subq1
")
}

Related

How to do a Sum(case when) using JPA

I don't have much background in converting between SQL and JPA-like code so I was wondering how I would go about converting the following to JPA syntax? Or if it's even possible? Thanks in advance.
SELECT DLR_CD, COUNT(*),
SUM(CASE WHEN CMPLT_DT='0001-01-01' THEN 1 END),
SUM(CASE WHEN CMPLT_DT!='0001-01-01' THEN 1 END),
SUM(CASE WHEN YEAR(CMPLT_DT) = YEAR(CURRENT DATE)-1 THEN 1 END),
SUM(CASE WHEN YEAR(CMPLT_DT) = YEAR(CURRENT DATE) THEN 1 END),
SUM(CASE WHEN (CMPLT_DT IS NULL OR CMPLT_DT='0001-01-01') THEN A.RPR_LBR_HR ELSE 0 END)
FROM <db2 table 1> A
join <db2 table 2> B
on ANUN_IND='A'
AND B.PIP_PSP_NO=A.PIP_PSP_NO
--OPTIONAL PARAMS GO HERE
GROUP BY DLR_CD
FOR FETCH ONLY WITH UR;
Edit: updated with full, barely-modified query.
Using criteria api it would look something like this:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<YourPojo> cq = cb.createQuery(YourPojo.class);
Root<Entity1> root = cq.from(Entity1.class);
Join<Entity1,Entity2> join = root.join(Entity1_.entity2,JoinType.LEFT);
/*
* the join by ID is implicit when using the .join method, the second
* condition is added as follows (Since you don't indicate the alias,
* I assume it is a field from table 2):
*/
join.on(cb.equal(join.get(Entity2_.anunInd),'A'));
Calendar dayOne = Calendar.getInstance();
dayOne.set(1, 0, 1);
//Expression for first and second sum case
Expression<Long> caseDate = cb.<Long>selectCase().when(cb.equal(root.get(Entity1_.cmpltDt),dayOne.getTime()), 1L).otherwise(0L);
Expression<Long> sumDate = cb.sum(caseDate);
//Expression for third sum case
Expression<Long> caseDateWithYearM1 = cb.<Long>selectCase().when(
cb.equal(cb.function("YEAR", Long.class, root.get(Entity1_.cmpltDt)),
cb.sum(cb.function("YEAR", Long.class, cb.literal(new Date())),-1))
, 1L).otherwise(0L);
Expression<Long> sumDateWithYearM1 = cb.sum(caseDateWithYearM1);
//Expression for fourth sun case
Expression<Long> caseDateWithYear = cb.<Long>selectCase().when(
cb.equal(cb.function("YEAR", Long.class, root.get(Entity1_.cmpltDt)),
cb.function("YEAR", Long.class, cb.literal(new Date())))
, 1L).otherwise(0L);
Expression<Long> sumDateWithYear = cb.sum(caseDateWithYear);
Expression<Long> caseNew = cb.<Long>selectCase().when(cb.or(
cb.equal(root.get(Entity1_.cmpltDt),dayOne.getTime()),
cb.equal(root.get(Entity1_.cmpltDt),dayOne.getTime())),
root.get(Entity1_.rprLbrHr)).otherwise(0L);
Expression<Long> sumNew = cb.sum(caseNew);
cq.multiselect(
root.get(Entity1_.dlrCd),
cb.count(root.get(Entity1_.dlrCd)),
sumDate,
sumDate,
sumDateWithYearM1,
sumDateWithYear,
sumNew
);
cq.groupBy(root.get(Entity1_.dlrCd));
List<YourPojo> resultado = entityManager.createQuery(cq).getResultList();
Your Pojo has to have a constructor with the same parameters (order and type) as the multiselect method.
The result query:
select
entity1.DLR_CD as col_0_0_,
count(entity1.DLR_CD) as col_1_0_,
sum(case when entity1.CMPLT_DT=? then 1 else 0
end) as col_2_0_,
sum(case when entity1.CMPLT_DT=? then 1 else 0
end) as col_3_0_,
sum(case when extract(year from entity1.CMPLT_DT)=extract(year from ?)+-1 then 1 else 0
end) as col_4_0_,
sum(case when extract(year from entity1.CMPLT_DT)=extract(year from ?) then 1 else 0
end) as col_5_0_ ,
sum(case when entity1.CMPLT_DT is null or entity1.CMPLT_DT=? then entity1.RPR_LBR_HR else 0
end) as col_6_0_,
from
entity1
left join
entity2 on entity1.PIP_PSP_NO = entity2.PIP_PSP_NO and
entity2.ANUN_IND='A'
group by
entity1.DLR_CD

Why wont my temp table populate data but the select statement inside of it will?

I have been stuck on a problem that has been a huge blocker for me. I cant seem to wrap my head around this issue and I was hoping someone can help provide me with some guidance.
So my problem is when I create my temp table, and I do
select * from all_subs
I get a blank table. However, when I test to run the select statement that comprises the temp table I get results...
My query looks like this
drop table if exists all_subs;
select sdb.id as subscription_id,
sdb.created_at,
sdb.user_id as user_id,
sdb.is_gift as is_gift,
case when pl.sku like '%auto-cancel%' then 1 else 0 end as is_auto_cancel,
sdb.current_period_ends_at as current_period_ends_at,
sdb.expires_at as expires_at,
sdb.current_period_started_at as current_period_started_at,
case when sdb.expires_at is null then 0 else 1 end as expiring,
case when pl.sku ilike '%mobi1' then 1
when pl.sku ilike '%mobi6' then 6
when pl.sku ilike '%mobi12' then 12
else pl.duration end as duration,
sdb.dog_name as dog_name,
sdb.dog_birthday as dog_birthday,
pl.sku as sku,
cast(round(100.0 * pl.price, 0) as int) as price,
cast(round(100.0 * pl.price / pl.duration, 0) as int) as mrr,
case
when sdb.expires_at is null and getdate() between sdb.current_period_started_at and sdb.current_period_ends_at then 'active'
when sdb.expires_at > getdate() then 'canceled'
when sdb.expires_at <= getdate() or (sdb.expires_at is null and sdb.current_period_ends_at < date_add('day',-30,getdate())) then 'expired'
else 'unknown'
end as subscription_state,
coalesce(can.no_new_products, false) as no_new_products,
coalesce(can.dog_did_not_like, false) as dog_did_not_like,
coalesce(can.not_enough_value, false) as not_enough_value,
coalesce(can.dog_died, false) as dog_died,
coalesce(can.cant_afford, false) as cant_afford,
coalesce(can.offer_accepted, false) as offer_accepted,
coalesce(can.too_big_too_small, false) as too_big_too_small,
coalesce(can.allergies, false) as allergies,
coalesce(can.too_much_treats, false) as too_much_treats,
coalesce(can.too_few_toys, false) as too_few_toys,
coalesce(can.toy_durability, false) as toy_durability,
coalesce(can.new_address, false) as new_address,
coalesce(can.something_different, false) as something_different,
case when ais.subscription_id is not null then 1 else 0 end add_item,
case when eets.subscription_id is not null then 1 else 0 end ever_extra_toy,
case when sdb.allergies = '{""}' then 0
when sdb.allergies is null then 0
else 1 end as is_allergy,
min(s.shipped_at) first_box_shipped_at,
count(distinct case when s.shipped_at is not null then o.id end) shipped_orders,
cast((case when (sdb.expires_at <= getdate() or (sdb.expires_at is null and sdb.current_period_ends_at < date_add('day',-30,getdate())))
and count(distinct case when s.shipped_at is not null then o.id end) = 0 then 1 else 0 end) as boolean) is_killed
into temp all_subs
from subscriptions as sdb
left join subscription_cancellation_summary as can on can.subscription_id = sdb.id
left join plans as pl on pl.id = sdb.current_plan_id
left join add_item_subs ais on ais.subscription_id = sdb.id
left join ever_extra_toy_subs eets on eets.subscription_id = sdb.id
left join orders o on o.orderable_type = 'Subscription' and o.orderable_id = sdb.id
left join orders_shipments os on os.order_id = o.id
left join shipments s on s.id = os.shipment_id
left join common.subs_dim sd on sd.subscription_id = sdb.id
where
-- Only valid subscriptions
sd.is_killed = false
group by sdb.id,
sdb.created_at,
sdb.user_id,
sdb.is_gift,
case when pl.sku like '%auto-cancel%' then 1 else 0 end,
sdb.current_period_ends_at,
sdb.expires_at,
sdb.current_period_started_at,
case when sdb.expires_at is null then 0 else 1 end,
case when pl.sku ilike '%mobi1' then 1
when pl.sku ilike '%mobi6' then 6
when pl.sku ilike '%mobi12' then 12
else pl.duration end,
sdb.dog_name,
sdb.dog_birthday,
pl.sku,
cast(round(100.0 * pl.price, 0) as int),
cast(round(100.0 * pl.price / pl.duration, 0) as int),
case
when sdb.expires_at is null and getdate() between sdb.current_period_started_at and sdb.current_period_ends_at then 'active'
when sdb.expires_at > getdate() then 'canceled'
when sdb.expires_at <= getdate() or (sdb.expires_at is null and sdb.current_period_ends_at < date_add('day',-30,getdate())) then 'expired'
else 'unknown'
end,
coalesce(can.no_new_products, false),
coalesce(can.dog_did_not_like, false),
coalesce(can.not_enough_value, false),
coalesce(can.dog_died, false),
coalesce(can.cant_afford, false),
coalesce(can.offer_accepted, false),
coalesce(can.too_big_too_small, false),
coalesce(can.allergies, false),
coalesce(can.too_much_treats, false),
coalesce(can.too_few_toys, false),
coalesce(can.toy_durability, false),
coalesce(can.new_address, false),
coalesce(can.something_different, false),
case when ais.subscription_id is not null then 1 else 0 end,
case when eets.subscription_id is not null then 1 else 0 end,
case when sdb.allergies = '{""}' then 0
when sdb.allergies is null then 0
else 1 end;
Has anybody come across this issue? Please help!
Thank you very much in advance
Try changing the
into temp all_subs
to
INTO TEMP TABLE all_subs

Adding a count of values

Is there another way I can sum up counts with less code?
I'm using a view (my only option) to try to find out if a customer spent money during any two of the last 5 calendar years
Table name:
V_PERSON
V_REVENUE
Columns:
V_PERSON.ID
V.REVENUE.PersonID
V.REVENUE.Year1 revenue for the year (currently 2016)
V.REVENUE.Year2 revenue for the year (currently, 2015)
V.REVENUE.Year3
V.REVENUE.Year4
V.REVENUE.Year5
Here's what I've tried:
SELECT V_PERSON.ID
FROM V_PERSON
WHERE
(
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year1 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year2 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year3 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year4 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year5 > 0
)
) >= 2
Here's one option using exists with multiple case statements:
select id
from person p
where exists (
select 1
from revenue r
where p.id = r.personid
and case when r.year1 > 0 then 1 else 0 end +
case when r.year2 > 0 then 1 else 0 end +
case when r.year3 > 0 then 1 else 0 end +
case when r.year4 > 0 then 1 else 0 end +
case when r.year5 > 0 then 1 else 0 end >= 2
)
How about a CASE statement:
SELECT V_PERSON.ID
FROM V_PERSON
WHERE
(
SELECT (case when V_REVENUE.Year1 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year2 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year3 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year4 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year5 > 0 then 1 else 0 end)
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID) >= 2

How to get rid of these co-related sub queries from select statement

Here I am dealing with only one table, It has an attribute called CmpltStscd where for each value I need a different column in the output as an aggregate function.
Is there a way to get rid of these subqueries ?
Trying a lot
Select
Mg.RsrcId
, Count(Mg.ActID) Num_of_Goals
, (SELECT COUNT(MC.ActID) FROM TM.MatrixGoal MC where MC.CmpltStsCd = 2 AND MG.RsrcID = MC.RsrcID AND MC.ActiveFlg = 1 AND MC.DelFlg = 0 AND MC.CorporateGoalFlg <> 1 AND MC.StsCd in (3,4)) as Complete
, (SELECT COUNT(MI.ActID) FROM TM.MatrixGoal MI where MI.CmpltStsCd = 4 AND MG.RsrcID = MI.RsrcID AND MI.ActiveFlg = 1 AND MI.DelFlg = 0 AND MI.CorporateGoalFlg <> 1 AND MI.StsCd in (3,4)) as Issues
, (SELECT COUNT(MO.ActID) FROM TM.MatrixGoal MO where MO.CmpltStsCd = 1 AND MG.RsrcID = MO.RsrcID AND MO.ActiveFlg = 1 AND MO.DelFlg = 0 AND MO.CorporateGoalFlg <> 1 AND MO.StsCd in (3,4)) as OnTrack
From
TM.MatrixGoal AS Mg
Where MG.ActiveFlg = 1
AND MG.DelFlg = 0
AND MG.CorporateGoalFlg <> 1
AND MG.StsCd in (3,4)
Group By RsrcId
You need a pivot/cross tab query
SELECT Mg.RsrcId,
COUNT(Mg.ActID) Num_of_Goals,
SUM(CASE
WHEN CmpltStsCd = 2 THEN 1
ELSE 0
END) AS Complete,
SUM(CASE
WHEN CmpltStsCd = 4 THEN 1
ELSE 0
END) AS Issues,
SUM(CASE
WHEN CmpltStsCd = 1 THEN 1
ELSE 0
END) AS OnTrack
FROM TM.MatrixGoal AS Mg
WHERE MG.ActiveFlg = 1
AND MG.DelFlg = 0
AND MG.CorporateGoalFlg <> 1
AND MG.StsCd IN ( 3, 4 )
GROUP BY RsrcId
I think you can just use conditional aggregation:
Select Mg.RsrcId, Count(Mg.ActID) Num_of_Goals,
SUM(CASE WHEN mg.CmpltStsCd = 2 THEN 1 ELSE 0 END) as Complete,
SUM(CASE WHEN mg.CmpltStsCd = 4 THEN 1 ELSE 0 END) as Issues
SUM(CASE WHEN mg.CmpltStsCd = 1 THEN 1 ELSE 0 END) as OnTrack
From TM.MatrixGoal Mg
Where MG.ActiveFlg = 1 AND MG.DelFlg = 0 AND MG.CorporateGoalFlg <> 1 AND
MG.StsCd in (3,4)
Group By RsrcId;

A subquery in a select causes my results to not return

Hello I have an issue with a very convoluted query, I did not write the query but I have to maintain it.
I have the below super long query which was working fine for a while(slow but fine) but some time in the last month it stopped working. we don't get an error it just times out returning results.
Now, if I run this fun query below with the first sub query within the selection criteria removed the results return the top 50 in 136 seconds.
If I leave it in it just times out after a few hours. Also to note if I take the sub query in the select statement and run it on it's own hard coding any values passed in to it returns the result in 0.004 seconds.
If I leave it all in but go to the very core query in this long query and put a restriction on the SDDOCO so it will return a single result I get the result in 94 seconds and it doesn't matter if I have the sub query in the select or not.
I think that one of the results is causing issues and bogging down the query but I can't think of a good way to figure out which item would cause this.. my result set when it returns is 47k records.
Any suggestions on where I can look or how I can investigate this further would be greatly appreciated.
SELECT
SUM((GL.GLAA/100) * (CAST(COALESCE((Select CXCRR from PRODDTA.F0015 F2 WHERE CXEFT = (SELECT MAX(CXEFT) FROM PRODDTA.F0015 F3 WHERE F3.CXEFT <= GL.GLDGJ) and CXCRCD = GL.GLCRCD AND CXCRDC ='USD'), 1) AS NUMERIC(15,4)))) TEST1,
SUM((GL.GLAA/100)) test2
FROM (SELECT MAX(SDAN8) SDAN8, MAX(SDMCU) SDMCU, MAX(SDDOCO) SDDOCO, MAX(SDDOC) SDDOC, MAX(SDSHAN) SDSHAN, CASE WHEN NVL(TRIM(TMURRF),' ') = ' ' then SDURRF ELSE TMURRF END SDURRF, MAX(SDDCTO) SDDCTO, MAX(SDDGL) SDDGL, MAX(SDASN) SDASN
, SUM(CASE WHEN IMGLPT like 'FG%' THEN (CASE WHEN NOT (UMCONV IS NULL) THEN SDSOQS/100 * UMCONV/10000000 else SDSOQS/100 END) ELSE 0 END) AS SDSOQS
, SUM(CASE WHEN IMGLPT = 'FG04' THEN (CASE WHEN NOT (UMCONV IS NULL) THEN SDSOQS/100 * UMCONV/10000000 ELSE SDSOQS/100 END) ELSE 0 END) AS AER_SDSOQS
, SUM(CASE WHEN IMGLPT like 'FG%' THEN (CASE WHEN SDSRP5 = '527' THEN (CASE WHEN NOT (UMCONV IS NULL) THEN SDSOQS/100 * UMCONV/10000000 ELSE SDSOQS/100 END) ELSE 0 END) ELSe 0 END) AS MDJ_SDSOQS
, MAX(SDIVD) SDIVD, MAX(SDADDJ) SDADDJ
, SUM(CASE WHEN SDWTUM = 'LB' THEN SDITWT WHEN UCCONV is not null then SDITWT*(UCCONV/10000000) WHEN CONV is not null THEN SDSOQS*CONV*10 ELSE 0 END)/10000 AS WEIGHT
,SUM(CASE WHEN IMGLPT like 'FG%' THEN
CASE
WHEN SDWTUM = 'LB' THEN SDITWT
WHEN UCCONV IS NOT NULL THEN SDITWT*(UCCONV/10000000)
WHEN CONV is not null THEN SDSOQS*CONV*10
ELSE 0 END
ELSE 0
end)/10000 as FG_WEIGHT,
SUM(CASE WHEN IMGLPT = 'FG04' THEN
CASE
WHEN SDWTUM = 'LB' THEN SDITWT
WHEN UCCONV IS NOT NULL THEN SDITWT*(UCCONV/10000000)
WHEN CONV is not null THEN SDSOQS*CONV*10
ELSE 0 END
ELSE 0
end)/10000 as AER_WEIGHT,
SUM(CASE WHEN SDSRP5 = '527' THEN
CASE
WHEN SDWTUM = 'LB' THEN SDITWT
WHEN UCCONV IS NOT NULL THEN SDITWT*(UCCONV/10000000)
WHEN CONV is not null THEN SDSOQS*CONV*10
ELSE 0 END
ELSE 0
end)/10000 as MDJ_WEIGHT,
SUM(CASE WHEN IMGLPT = 'FG07' THEN
CASE
WHEN SDWTUM = 'LB' THEN SDITWT
WHEN UCCONV IS NOT NULL THEN SDITWT*(UCCONV/10000000)
WHEN CONV is not null THEN SDSOQS*CONV*10
ELSE 0 END
ELSE 0
end)/10000 as MDJ_3rdParty_WEIGHT, max(SDCARS) SDCARS
FROM PRODDTA.F42119
left join proddta.F554202x on trim(SDURRF) = trim(TMUSRRSV1) and SDDOCO = TMDOCO
LEFT JOIN PRODDTA.F4101 ON IMITM = SDITM
LEFT JOIN PRODDTA.F41002 ON UMITM = SDITM AND SDMCU = UMMCU AND SDUOM = UMUM AND UMRUM = imuom1
left join PRODDTA.F41003 on UCUM = SDWTUM and UCRUM = 'LB'
Left JOin (SELECT UMMCU as MCU, UMITM as ITM, UMUM as UM, max(CASE WHEN UMRUM = 'LB' THEN UMCONV/10000000 ELSE UMCONV/10000000 * UCCONV/10000000 END) AS CONV
FROM PRODDTA.F41002
LEFT JOIN PRODDTA.F41003
ON UMRUM = UCUM
WHERE (UCRUM = 'LB' OR UMRUM = 'LB')
GROUP BY UMMCU, UMITM, UMUM) CONV2
ON MCU = SDMCU AND ITM = SDITM AND UM = SDUOM
WHERE SDLNTY = 'S'
AND SDSOQS > 0
and not ((SDLTTR = 980 AND SDNXTR = 999) OR SDSOCN = SDUORG)
and SDSRP1 <> 'BLK'
and not exists (select SDDOCO from proddta.F42119 GA where SDADDJ >= FISCALPERIODSTART(14,1) and SDADDJ <= FISCALPERIODEND(14,12) and SDUOM = 'GA' and F42119.SDDOCO = GA.SDDOCO)
and SDDOCO in (1230256,1227461,1230628,1225291,1225297,1231601,1242703,1248671,1249556,1244905)
GROUP BY CASE WHEN NVL(TRIM(TMURRF),' ') = ' ' then SDURRF ELSE TMURRF END) DTL
Left JOIN PRODDTA.F0101 BT ON BT.ABAN8 = DTL.SDAN8
Left JOIN PRODDTA.F0101 ST ON ST.ABAN8 = DTL.SDSHAN
INNER JOIN PRODDTA.F0911 GL
ON TRIM(GL.GLEXR) = TRIM(DTL.SDURRF)
WHERE GLDCT = 'PV' AND GLDGJ >= KIKDATETOJUL(KIKE1JULTODATE(FISCALPERIODSTART(14,1)) - 90) and GLDGJ <= KIKDATETOJUL(KIKE1JULTODATE(FISCALPERIODEND(14,12)) + 90) AND GLOBJ IN ('5025','5026') AND GLLT ='AA' AND GLEXTL <> 'AM' AND GLEXR <> ' ' and GLRE = ' '
GROUP BY GL.GLEXR, GL.GLDCT,
CASE WHEN SDDCTO IN ('ST','SJ') THEN CAST(SDSHAN AS NCHAR(12)) ELSE TRIM(SDMCU) END, DTL.SDASN, DTL.SDDOC, DTL.SDDOCO, DTL.SDDCTO, DTL.SDSOQS, DTL.AER_SDSOQS, DTL.MDJ_SDSOQS, DTL.SDSHAN, DTL.SDAN8, SDURRF, GL.GLSUB, Weight, FG_Weight, AER_WEIGHT, MDJ_WEIGHT, MDJ_3rdParty_WEIGHT
We where provided with the below code to run ahead of the select statement which changes the way the Oracle DB optimizes the query.
alter session set optimizer_index_caching=0;
alter session set optimizer_index_cost_adj=80;
This fixed the issue.