How to do a Sum(case when) using JPA - sql

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

Related

How do I replace null with 0 in SUM CASE WHEN statement?

I am using a CASE WHEN statement and a SUM function. I want to replace all nulls with 0.
I tried adding a 0 at the end of my statement.
This is my current code
select ID, PT_Number,
ORGANIZATION,
[Approved] = sum(case when PT_TYPE = 'Lend' then Approved END),
[Disbursed] = sum(case when PT_TYPE = 'Give' then Disbursed end),
[Repaid] = sum(case when PT_TYPE = 'Pay' then Payment end)
from TABLE1
group by ID, PT_Number,
ORGANIZATION
This is what I am trying
[Approved] = sum(case when PT_TYPE = 'Lend' then Approved END, 0),
[Disbursed] = sum(case when PT_TYPE = 'Give' then Disbursed end, 0),
[Repaid] = sum(case when PT_TYPE = 'Pay' then Payment end, 0)
Just add an else clause:
select ID, PT_Number,
ORGANIZATION,
[Approved] = sum(case when PT_TYPE = 'Lend' then Approved else 0 END),
[Disbursed] = sum(case when PT_TYPE = 'Give' then Disbursed else 0 end),
[Repaid] = sum(case when PT_TYPE = 'Pay' then Payment else 0 end)
from TABLE1
group by ID, PT_Number, ORGANIZATION;
You could also use coalesce() but that seems like overkill.

SQL XML dd/mm/yyyy failing to return as string

I am working with a legacy system that only accepts dd/mm/yyyy in the XML for the data fields otherwise it mucks up the data entry.
I have tried every which way to attempt to force my data fields to display as dd/mm/yyyy, I have attempted to CONVERT to DATETIME 103, I have tried declaring it as a VARCHAR and everytime time it returns as 2018-05-11 for example.
How can I force the returned field to display as DD/MM/YYYY, this is a snippet of my code, excuse how messy it is unfortunately it is very linear and the system that accepts the XML is very basic.
SELECT TOP 1 1 'job/queue',
#Branch 'job/branch',
CASE WHEN myli.PolRef# IS NOT NULL THEN 'update-broomsrisk' ELSE 'create-broomsrisk' END 'parameters/yzt/char20.1',
SUBSTRING(#PolicyRef,1,6) 'broomsdata/broomsclient/bcm/refno',
#PolicyRef 'broomsdata/broomspolicy/bpy/refno',
CASE WHEN myli.PolRef# IS NOT NULL THEN myli.key# ELSE NULL END 'broomsdata/broomspolicy/myli/KEY',
(SELECT ISNULL(ct2.convictiondate,ct2.offencedate) FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 1) 'broomsdata/broomspolicy/myli/Date1',
(SELECT ct2.code FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 1) 'broomsdata/broomspolicy/myli/Code1',
(SELECT ct2.fine FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 1) 'broomsdata/broomspolicy/myli/Fine1',
(SELECT ct2.noofpoints FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 1) 'broomsdata/broomspolicy/myli/Points1',
(SELECT ISNULL(ct2.convictiondate,ct2.offencedate) FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 2) 'broomsdata/broomspolicy/myli/Date2',
(SELECT ct2.code FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 2) 'broomsdata/broomspolicy/myli/Code2',
(SELECT ct2.fine FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 2) 'broomsdata/broomspolicy/myli/Fine2',
(SELECT ct2.noofpoints FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 2) 'broomsdata/broomspolicy/myli/Points2',
(SELECT ISNULL(ct2.convictiondate,ct2.offencedate) FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 3) 'broomsdata/broomspolicy/myli/Date3',
(SELECT ct2.code FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 3) 'broomsdata/broomspolicy/myli/Code3',
(SELECT ct2.fine FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 3) 'broomsdata/broomspolicy/myli/Fine3',
(SELECT ct2.noofpoints FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 3) 'broomsdata/broomspolicy/myli/Points3',
(SELECT ISNULL(ct2.convictiondate,ct2.offencedate) FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 4) 'broomsdata/broomspolicy/myli/Date4',
(SELECT ct2.code FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 4) 'broomsdata/broomspolicy/myli/Code4',
(SELECT ct2.fine FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 4) 'broomsdata/broomspolicy/myli/Fine4',
(SELECT ct2.noofpoints FROM #ConvictionTable AS ct2 WHERE ct2.RowNo = 4) 'broomsdata/broomspolicy/myli/Points4'
FROM #ConvictionTable AS ct
LEFT OUTER JOIN [FIG-SQL-SRV].InfoCentre.dbo.ic_BD_MYLI AS myli ON ct.branch = myli.B# AND ct.policyRef = myli.PolRef#
FOR XML PATH('xmlexecute'), TYPE;
The Fields I'm trying to force are the 'Date1'/'Date2' etc. fields.
Cheers
Use CONVERT(varchar(10), YourDateColumn, 103). I think your mistake was trying to convert to a datetime (I'm guessing you tried CONVERT(datetime, YourDateColumn, 103)) while using a style code; date/time datatypes, in SQL Server, have no format. Trying to format them won't do anything.
For example: SELECT CONVERT(varchar(10), GETDATE(), 103); returns the varchar(10) value '11/05/2018'.
Edit: The below is to (temporary) assist the OP in showing how i create XML for OpenInterchange. The OP is using a lot of Sub Selects, something that doesn't help the speed of the query. I've highlighted, a couple of points for the OP to note as well:
SELECT K.Insco AS Insurer,
K.B# AS Branch,
K.PolRef# AS PolicyRef,
K.ClaimRef# AS ClaimRef,
--XML Generation starts here.
(SELECT(SELECT K.B# AS branch,
'OO' AS operator,
'PDF' AS printtype
FOR XML PATH('job'),TYPE),
(SELECT (SELECT 'update-claim' AS [Char20.1]
FOR XML PATH('yzt'),TYPE)
FOR XML PATH('parameters'),TYPE),
(SELECT (SELECT (SELECT K.Ref# AS Refno
FOR XML PATH('bcm'),TYPE)
FOR XML PATH('broomsclient'),TYPE),
(SELECT (SELECT K.PolRef# AS Refno
FOR XML PATH('bpy'),TYPE)
FOR XML PATH('broomspolicy'),TYPE),
(SELECT (SELECT K.ClaimRef# AS [Claim.No],
K.[Claim No] AS [Ins.Claim.Ref],
K.KGMSettled AS [Claim.Settled],
K.KGMReserve AS [Claim.Reserve],
K.KGMReserve + K.KGMSettled As [Claim.Amount],
K.KGMStatus AS [Stat.Desc],
CASE K.KGMStatus WHEN 'Settled' THEN 'SETT'
WHEN 'Ouststanding' THEN 'OUTS'
WHEN 'Declined' THEN 'DECL'
WHEN 'Not Taken up' THEN 'NTUP'
WHEN 'Withdrawn' THEN 'WITH' END AS [stat.code],
CONVERT(varchar(10),K.[Notified Date],103) AS [Date.repd], --First example of the dd/MM/yyyy format
CONVERT(varchar(10),K.[Loss Date],103) AS [Loss.date], --Another example of the dd/MM/yyyy format
CASE WHEN K.[Date Closed] IS NOT NULL THEN CONVERT(varchar(10), GETDATE(), 103) END AS [Stat.date], -- and another example of the dd/MM/yyyy format
CONVERT(varchar(10),K.[Date Closed],103) AS [Date.Settled], --you get the idea. :)
CASE WHEN K.[Date Closed] IS NOT NULL AND K.[Incident Type] = 'Windscreen' THEN 'Yes'
WHEN K.[Date Closed] IS NULL THEN ''
WHEN K.[NCB Decision] = 'Allowed' THEN 'Yes'
WHEN K.[NCB Decision] = 'Disallowed' THEN 'Yes' END AS [Settled.free]
/*
CASE WHEN K.[Date Closed] IS NOT NULL AND K.[Incident Type] = 'Windscreen' THEN 'Yes'
WHEN K.KGMReserve + K.KGMSettled = 0 AND K.[Date Closed] IS NOT NULL THEN 'Yes'
WHEN K.KGMReserve + K.KGMSettled > 0 AND K.[Date Closed] IS NOT NULL THEN 'No'
ELSE '' END AS [Settled.free]*/
FOR XML PATH('bch'),TYPE),
(SELECT K.BCAKey AS [KEY],
K.[Vehicle Reg# No] AS [Reg.no],
K.[Driver Name] AS [Driver],
K.[ AD Paid] AS [Pay.ad],
K.[AD Reserve] AS [Reserve.ad],
K.[TPD Paid] + K.[TPI Paid] AS [Pay.tp],
K.[TPD Reserve] + K.[TPI Reserve] AS [Reserve.tp],
--K.[TPI Paid] AS [Pay.others],
--K.[TPI Reserve] AS [Reserve.others],
0 AS [Pay.others],
0 AS [Reserve.others],
K.KGMSettled AS [Pay.total],
K.KGMReserve AS [Reserve.Total],
K.[Recovery] AS [Pay.recovs],
K.[AD Recovery Reserve] AS [Reserve.recovs],
'Updated by FileDrop Service. XML Generated on ' + CONVERT(varchar(10),GETDATE(),103) as [Remarks4]
FOR XML PATH('bca'),TYPE),
(SELECT CONVERT(varchar(10),GETDATE(),103) AS [date],
LEFT(CONVERT(varchar(10),GETDATE(),108),5) AS [time],
'OO' AS [op],
'FileDrop' AS [Name],
K.KGMSettled AS [Settled],
K.KGMReserve AS [Reserve],
K.KGMSettled + K.KGMReserve As [Total],
--CONVERT(varchar(10),K.DataToDate,103) AS [EffDate],
CASE WHEN K.KGMSettled != K.BCHSettled THEN 'Payment'
WHEN K.KGMReserve != K.BCHReserve THEN 'Reserve Adjustment'
ELSE 'Payment' END AS [Notes]
FOR XML PATH('clam'),TYPE)
FOR XML PATH('broomsclaim'),TYPE)
FOR XML PATH('broomsdata'),TYPE)
FOR XML PATH('xmlexecute'),TYPE) AS InputXML,
GETDATE() AS DateGenerated,
0 AS TestLoad
FROM KGMCGStandard_viw K
WHERE K.ClaimsFound = 1
AND K.KGMFound = 1
AND (K.KGMSettled != K.BCHSettled
OR K.KGMReserve != K.BCHReserve
OR (CONVERT(date,K.KGMClosure) != CONVERT(date,BCHClosure)
OR (K.KGMClosure IS NULL AND K.BCHClosure IS NOT NULL)
OR (K.KGMClosure IS NOT NULL AND K.BCHClosure IS NULL))
OR (CASE WHEN K.[Date Closed] IS NOT NULL AND K.[Incident Type] = 'Windscreen' THEN 'Yes'
WHEN K.[NCB Decision] = 'Allowed' THEN 'Yes'
WHEN K.[NCB Decision] = 'Disallowed' THEN 'No' END != K.Settled_Free
OR (K.[Date Closed] IS NULL AND K.Settled_free IS NULL)))
AND NOT EXISTS (SELECT 1
FROM AutoloadXML_tbl A
WHERE A.Branch = K.B#
AND A.PolicyRef = K.PolRef#
AND A.ClaimRef = K.ClaimRef#
AND (A.DateSubmitted IS NULL
OR A.Installed = 0))
ORDER BY K.ClaimRef# ASC;
Since you already figured out the date part I will leave that up to you but your query could be simplified majorly using conditional aggregation. I used square braces around the column names instead of single quotes. Sure those work but I consider that a bad habit because it is difficult to decide if it is a string literal or a column alias. I also prefer to use alias = but that is more a preference thing. I also prefer leading commas which is also a preference thing.
Pretty sure this query should do the same thing.
SELECT 1 as 'job/queue',
#Branch as 'job/branch',
CASE WHEN myli.PolRef# IS NOT NULL THEN 'update-broomsrisk' ELSE 'create-broomsrisk' END as 'parameters/yzt/char20.1',
SUBSTRING(#PolicyRef,1,6) as 'broomsdata/broomsclient/bcm/refno',
#PolicyRef as 'broomsdata/broomspolicy/bpy/refno',
CASE WHEN myli.PolRef# IS NOT NULL THEN myli.key# ELSE NULL END as 'broomsdata/broomspolicy/myli/KEY'
, [broomsdata/broomspolicy/myli/Date1] = max(case when ct.RowNo = 1 then ISNULL(ct.convictiondate, ct.offencedate) end)
, [broomsdata/broomspolicy/myli/Code1] = max(case when ct.RowNo = 1 then ct.code end)
, [broomsdata/broomspolicy/myli/Fine1] = max(case when ct.RowNo = 1 then ct.fine end)
, [broomsdata/broomspolicy/myli/Points1] = max(case when ct.RowNo = 1 then ct.noofpoints end)
, [broomsdata/broomspolicy/myli/Date2] = max(case when ct.RowNo = 2 then ISNULL(ct.convictiondate, ct.offencedate) end)
, [broomsdata/broomspolicy/myli/Code2] = max(case when ct.RowNo = 2 then ct.code end)
, [broomsdata/broomspolicy/myli/Fine2] = max(case when ct.RowNo = 2 then ct.fine end)
, [broomsdata/broomspolicy/myli/Points] = max(case when ct.RowNo = 2 then ct.noofpoints end)
, [broomsdata/broomspolicy/myli/Date3] = max(case when ct.RowNo = 3 then ISNULL(ct.convictiondate, ct.offencedate) end)
, [broomsdata/broomspolicy/myli/Code3] = max(case when ct.RowNo = 3 then ct.code end)
, [broomsdata/broomspolicy/myli/Fine3] = max(case when ct.RowNo = 3 then ct.fine end)
, [broomsdata/broomspolicy/myli/Points3] = max(case when ct.RowNo = 3 then ct.noofpoints end)
, [broomsdata/broomspolicy/myli/Date4] = max(case when ct.RowNo = 4 then ISNULL(ct.convictiondate, ct.offencedate) end)
, [broomsdata/broomspolicy/myli/Code4] = max(case when ct.RowNo = 4 then ct.code end)
, [broomsdata/broomspolicy/myli/Fine4] = max(case when ct.RowNo = 4 then ct.fine end)
, [broomsdata/broomspolicy/myli/Points4] = max(case when ct.RowNo = 4 then ct.noofpoints end)
FROM #ConvictionTable AS ct
LEFT OUTER JOIN [FIG-SQL-SRV].InfoCentre.dbo.ic_BD_MYLI AS myli ON ct.branch = myli.B# AND ct.policyRef = myli.PolRef#
GROUP BY #Branch
, CASE WHEN myli.PolRef# IS NOT NULL THEN 'update-broomsrisk' ELSE 'create-broomsrisk' END
, SUBSTRING(#PolicyRef,1,6)
, #PolicyRef
, CASE WHEN myli.PolRef# IS NOT NULL THEN myli.key# ELSE NULL END
FOR XML PATH('xmlexecute'), TYPE

How do I escape <> for this SQL in a XML file

I am trying to store the following sql in a bean within an XML file. I am trying to escape the greater than and less than signs, however I seem to still be getting an error in Eclipse. I must not understand how to properly escape these signs. I count six less than and greater than signs, which I have attempted to escape.
Here's my attempt:
<property name="SQL" value="<><><><><><>"
"SELECT TO_CHAR(SYSDATE,'YYYY-MM-DD') SQL_RUN_DT
,'STG_DISB_HOLD_TH' SRC_TBL
,A1.DISB_DT
,A1.CPC
,A1.AWARD_YR
,COUNT(1) ROW_CNT
,SUM(A1.APPL_NBR) APPL_NBR_SUM
,SUM(A1.TSYS_SCHL_ID) TSYS_SCHL_ID_SUM
,SUM(TO_NUMBER(A1.DISB_NBR)) DISB_NBR_SUM
,SUM(A1.DISB_SEQ_NBR) DISB_SEQ_NBR_SUM
,SUM(CASE WHEN A1.DISB_STAT_CD = 'R' AND A1.DISB_SEQ_NBR = 1 THEN 1
ELSE A1.INTNL_APPL_SEQ_NBR + 1
END) INTERNAL_DISB_SEQ_SUM
,MIN(A1.DISB_RCVD_DT) DISB_RCVD_DT_MIN
,MAX(A1.DISB_RCVD_DT) DISB_RCVD_DT_MAX
,SUM(CASE WHEN A1.DISB_STAT_CD = 'P' THEN 1 ELSE 0 END) DISB_STAT_CD_P
,SUM(CASE WHEN A1.DISB_STAT_CD = 'R' THEN 1 ELSE 0 END) DISB_STAT_CD_R
,MIN(A1.PYMT_START_DT) PYMT_START_DT_MIN
,MAX(A1.PYMT_START_DT) PYMT_START_DT_MAX
,COUNT(DISTINCT A1.SCHL_ENROLL_CD) SCHL_ENROLL_CD_CNT
,SUM(TO_NUMBER(A1.NET_TRANS_CD)) NET_TRANS_CD_SUM
,SUM(A1.NET_TRANS_AMT) NET_TRANS_AMT_SUM
,SUM(CASE WHEN A1.DISB_STAT_CD = 'R' AND A1.DISB_SEQ_NBR = 1 AND A1.NET_C_OR_D_IND = 'D' THEN A1.NET_TRANS_AMT + A1.NET_TRANS_AMT
WHEN A1.DISB_STAT_CD = 'R' AND A1.DISB_SEQ_NBR = 1 AND A1.NET_C_OR_D_IND <> 'D' THEN A1.NET_TRANS_AMT - A1.NET_TRANS_AMT
WHEN (A1.DISB_STAT_CD <> 'R' OR A1.DISB_SEQ_NBR <> 1) AND A1.NET_C_OR_D_IND = 'D' THEN A1.SUM_NET_AMT + A1.NET_TRANS_AMT
WHEN (A1.DISB_STAT_CD <> 'R' OR A1.DISB_SEQ_NBR <> 1) AND A1.NET_C_OR_D_IND <> 'D' THEN A1.SUM_NET_AMT - A1.NET_TRANS_AMT
ELSE 0
END) SUM_NET_AMT_SUM
,SUM(CASE WHEN A1.ENRL_STATUS_CD = 'F' THEN 1 ELSE 0 END) ENRL_STATUS_CD_F
,SUM(CASE WHEN A1.ENRL_STATUS_CD = 'Q' THEN 1 ELSE 0 END) ENRL_STATUS_CD_Q
,SUM(CASE WHEN A1.ENRL_STATUS_CD = 'H' THEN 1 ELSE 0 END) ENRL_STATUS_CD_H
,SUM(CASE WHEN A1.ENRL_STATUS_CD = 'L' THEN 1 ELSE 0 END) ENRL_STATUS_CD_L
,SUM(CASE WHEN A1.ENRL_STATUS_CD IS NULL THEN 1 ELSE 0 END) ENRL_STATUS_CD_NULL
,COUNT(DISTINCT A1.PGM_CIP_CD) PGM_CIP_CD_CNT
,COUNT(DISTINCT A1.LEGACY_USER_ID) LEGACY_USER_ID_CNT
,COUNT(DISTINCT A1.MAINT_APP) MAINT_APP_CNT
,MIN(A1.MAINT_DTM) MAINT_DTM_MIN
,MAX(A1.MAINT_DTM) MAINT_DTM_MAX
,COUNT(DISTINCT A1.MAINT_USERID) MAINT_USERID_CNT
FROM
(
SELECT LM.TEACH_MASTER_ID
,SAM.APPL_NBR
,TO_NUMBER(SAM.AWARD_YR) AWARD_YR
,SAM.TSYS_SCHL_ID
,SAM.AWARD_NBR
,SAM.DISB_NBR
,SAM.DISB_SEQ_NBR
,SAM.CPC
,SAM.DISB_DT
,SAM.DISB_RCVD_DT
,SAM.DISB_STAT_CD
,SAM.PYMT_START_DT
,SAM.SCHL_ENROLL_CD
,SAM.NET_TRANS_CD
,CASE WHEN SAM.NET_C_OR_D_IND = 'C' THEN SAM.NET_TRANS_AMT * -1
WHEN SAM.NET_C_OR_D_IND IS NULL THEN 0
ELSE SAM.NET_TRANS_AMT
END NET_TRANS_AMT
,CASE WHEN SAM.NET_C_OR_D_IND = 'C' THEN SAM.GROSS_TRANS_AMT * -1
WHEN SAM.NET_C_OR_D_IND IS NULL THEN 0
ELSE SAM.GROSS_TRANS_AMT
END GROSS_TRANS_AMT
,CASE WHEN SAM.NET_C_OR_D_IND = 'C' THEN SAM.FEE_TRANS_AMT * -1
WHEN SAM.NET_C_OR_D_IND IS NULL THEN 0
ELSE SAM.FEE_TRANS_AMT
END FEE_TRANS_AMT
,CASE WHEN SAM.NET_C_OR_D_IND = 'C' THEN SAM.REBATE_TRANS_AMT * -1
WHEN SAM.NET_C_OR_D_IND IS NULL THEN 0
ELSE SAM.REBATE_TRANS_AMT
END REBATE_TRANS_AMT
,SAM.MAINT_DTM
,SAM.MAINT_USERID
,SAM.ENRL_STATUS_CD
,SAM.PGM_CIP_CD
,'BATCH' AS LEGACY_USER_ID
,'BATCH' AS MAINT_APP
,SAM.NET_C_OR_D_IND
,ROW_NUMBER() OVER (PARTITION BY SAM.APPL_NBR, SAM.AWARD_YR, SAM.TSYS_SCHL_ID, SAM.AWARD_NBR, SAM.DISB_NBR
ORDER BY DTSEQ.INTNL_APPL_SEQ_NBR DESC) ROW_NUM_PART
,COALESCE(DTSEQ.INTNL_APPL_SEQ_NBR,0) INTNL_APPL_SEQ_NBR
,DTSEQ.CHG_GROSS_TRANS_AMT DT_CHG_GROSS_TRANS_AMT
,DTSEQ.CHG_NET_TRANS_AMT DT_CHG_NET_TRANS_AMT
,DTSEQ.CHG_FEE_TRANS_AMT DT_CHG_FEE_TRANS_AMT
,DTSEQ.CHG_REBATE_TRANS_AMT DT_CHG_REBATE_TRANS_AMT
,COALESCE(DTSEQ.SUM_GROSS_AMT,0) SUM_GROSS_AMT
,COALESCE(DTSEQ.SUM_NET_AMT,0) SUM_NET_AMT
,COALESCE(DTSEQ.SUM_FEE_AMT,0) SUM_FEE_AMT
,COALESCE(DTSEQ.SUM_REBATE_AMT,0) SUM_REBATE_AMT
FROM MYSCHEMA.TEACH_MASTER LM
JOIN MYSCHEMA.STG_DISB_HOLD SAM
ON LM.APP_NUM_LEGACY = SAM.APPL_NBR
AND LM.ATTEND_SCHL_MASTER_ID = SAM.TSYS_SCHL_ID
AND LM.AWARD_YR = TO_NUMBER(SAM.AWARD_YR)
LEFT JOIN MYSCHEMA.STG_DISB_TRANS DTSEQ
ON SAM.APPL_NBR = DTSEQ.APPL_NBR
AND SAM.AWARD_YR = DTSEQ.AWARD_YR
AND SAM.TSYS_SCHL_ID = DTSEQ.TSYS_SCHL_ID
AND SAM.AWARD_NBR = DTSEQ.AWARD_NBR
AND SAM.DISB_NBR = DTSEQ.DISB_NBR
WHERE SAM.DISB_STAT_CD IN ('R','P')
AND SAM.NET_TRANS_CD IN ('0102','0131','0161','0189','0200')
) A1
WHERE A1.ROW_NUM_PART = 1
GROUP BY TO_CHAR(SYSDATE,'YYYY-MM-DD')
,'STG_DISB_HOLD_TH'
,A1.DISB_DT
,A1.CPC
,A1.AWARD_YR
;"/>
You have to escape them ALL:
WHEN A1.DISB_STAT_CD [..snip..] A1.NET_C_OR_D_IND <> 'D' THEN A1.NET_TRANS_AMT - A1.NET_TRANS_AMT
^^--missed a bunch of these
Plus, this next bit makes no sense:
<property name="SQL" value="<><><><><><>"
^---start attribute end attribute --^
"SELECT TO_CHAR(SYSDATE,'YYYY-MM-DD') SQL_RUN_DT
^---attribute value with no name for it

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.