where clause, case statement - sql

I need to have the case statement shown below added to the main query so that it excludes members when different dates. How can I add it in? Thanks.
SELECT DISTINCT
PI.INDEX_VALUE,
LB.STATE,
UNIQUE_ID,
'AL',
'EN',
MBP.START_DATE,
ADD_MONTHS(MBP.START_DATE,12)
FROM dwteam.PATIENT_DETAILS PD
INNER JOIN dwteam.ADMIN_CLIENT AC
ON AC.CLIENT_ID = PD.CLIENT_ID
and AC.DELETED_BY is null
-- and AC.IS_ACTIVE =1
INNER JOIN dwteam.MEM_BENF_PROG MBP
ON MBP.MEMBER_ID = PD.PATIENT_ID
and MBP.DELETED_BY is null
INNER JOIN dwteam.BENF_PLAN_PROG BPP
ON BPP.BEN_PLAN_PROG_ID = MBP.BEN_PLAN_PROG_ID
INNER JOIN dwteam.BENEFIT_PROGRAM BPR
ON BPR.BENEFIT_PROGRAM_ID = BPP.BENEFIT_PROGRAM_ID
and BPR.DELETED_BY is null
left JOIN dwteam.PATIENT_INDEX PI
ON PI.PATIENT_ID=MBP.MEMBER_ID
AND PI.INDEX_ID in (10073,10071)
left join UHG_000613129.HFS_LOB_ID_XWALK LB
on trim(upper(replace(replace(AC.CLIENT_NAME,'C&S',''),'M&R','')))=trim(upper(STATE_DESC))
WHERE PROGRAM_NAME IN ('Healthy Pregnancy','High Risk Pregnancy')
AND (sysdate < ADD_MONTHS(MBP.START_DATE,12)
OR sysdate < ADD_MONTHS(MBP.END_DATE,12))
CASE WHEN MBP.CLOSURE_ID = 40 THEN MBP.END_DATE - 120
WHEN MBP.CLOSURE_ID IN (5,18,103) THEN MBP.END_DATE - 365
ELSE MBP.END_DATE - 270 END AS END_DATE

You can use a CTE to name an expression, and then use it for any purpose you want in the outer query.
I don't know all the details of your query but it should take the following form:
with
x as (
SELECT DISTINCT
PI.INDEX_VALUE,
LB.STATE,
UNIQUE_ID,
'AL',
'EN',
MBP.START_DATE,
ADD_MONTHS(MBP.START_DATE,12) as m1,
CASE WHEN MBP.CLOSURE_ID = 40 THEN MBP.END_DATE - 120
WHEN MBP.CLOSURE_ID IN (5,18,103) THEN MBP.END_DATE - 365
ELSE MBP.END_DATE - 270 END AS END_DATE1
FROM dwteam.PATIENT_DETAILS PD
JOIN dwteam.ADMIN_CLIENT AC ON AC.CLIENT_ID = PD.CLIENT_ID
AND AC.DELETED_BY is null
JOIN dwteam.MEM_BENF_PROG MBP ON MBP.MEMBER_ID = PD.PATIENT_ID
AND MBP.DELETED_BY is null
JOIN dwteam.BENF_PLAN_PROG BPP ON BPP.BEN_PLAN_PROG_ID
= MBP.BEN_PLAN_PROG_ID
JOIN dwteam.BENEFIT_PROGRAM BPR ON BPR.BENEFIT_PROGRAM_ID
= BPP.BENEFIT_PROGRAM_ID
AND BPR.DELETED_BY is null
left JOIN dwteam.PATIENT_INDEX PI ON PI.PATIENT_ID=MBP.MEMBER_ID
AND PI.INDEX_ID in (10073,10071)
left join UHG_000613129.HFS_LOB_ID_XWALK LB
on trim(upper(replace(replace(AC.CLIENT_NAME,'C&S',''),'M&R','')))
= trim(upper(STATE_DESC))
WHERE PROGRAM_NAME IN ('Healthy Pregnancy','High Risk Pregnancy')
AND (sysdate < ADD_MONTHS(MBP.START_DATE,12)
OR sysdate < ADD_MONTHS(MBP.END_DATE,12))
)
SELECT *
FROM x
WHERE end_date1 > ... -- filtering predicate(s) using a named expression
Tweak as necessary.

Related

SQL Poor Performance on join query

i'm experiencing really poor performance with this query, probably because of my poor experience with join.
The following query have to run on a DB2 database.
SELECT A.n_ann_ord
|| A.n_prg_ord AS numeroOrdine,
DATE(B.d_ins) AS dataInserimentoEGO,
DATE(A.d_ord) AS dataInserimento,
C.n_lot_prd AS lotto,
E.t_rag_soc AS consorzio,
D.t_rag_soc AS cliente,
b.c_obu_new AS obuid,
j.c_tar AS targa,
j.c_naz AS nazione,
C.c_pos AS postazione,
CASE
WHEN B.f_ric_obu_sat = 'S' THEN 'Satellitare'
ELSE 'Non Satellitare'
END AS tipoTitolo,
F.t_des AS statoOrdine,
CASE
WHEN (SELECT 1
FROM evda.tetsau_sos_tit_mul X
WHERE x.d_ord = a.d_ord
FETCH first ROW only) = 1 THEN 'S'
ELSE 'N'
END AS SOSTITUZIONE,
DATE(G.d_ape_pro) AS aperturaLotto,
DATE(G.d_chiu_pro) AS chiusuraLotto,
DATE(G.d_com_con) AS confezionamento,
DATE(C.d_spe_spe) AS spedizione,
C.c_ide_spe AS trackingNumber,
DATE(H.d_acq_con) AS consegna
FROM evda.tetsvi_ord A
JOIN evda.tets3t_int_srv B
ON A.c_ctp_cli = B.c_ctp_cli
AND A.d_ord = B.d_ord
JOIN evda.tetski_int_con_ord C
ON A.c_ctp_cli = C.c_ctp_cli
AND A.d_ord = C.d_ord
JOIN evda.tets25_ctp D
ON C.c_ctp_cli = D.c_ctp
JOIN evda.tets25_ctp E
ON C.c_ctp_con = E.c_ctp
JOIN evda.tetsvk_sta_ord F
ON A.c_sta_ord = F.c_sta_ord
JOIN evda.tetsvp_pre_tit I
ON a.c_ctp_cli = i.c_ctp_cli
AND a.d_ord = i.d_ord
JOIN evda.tetsmj_tit_pre_est J
ON a.c_ctp_cli = j.c_ctp_cli
AND a.d_ord = j.d_ord
AND b.n_prg_tit_pre = j.n_prg
LEFT JOIN evda.tetskk_lot_prd G
ON C.n_lot_prd = G.n_lot_prd
LEFT JOIN evda.tets3u_int_srv_spe H
ON B.d_ins = H.d_ins
WHERE DATE(a.d_ord) <= CURRENT_DATE
AND DATE(a.d_ord) >= CURRENT_DATE - 30 DAYS
GROUP BY A.n_ann_ord
|| A.n_prg_ord,
DATE(B.d_ins),
DATE(A.d_ord),
C.n_lot_prd,
E.t_rag_soc,
D.t_rag_soc,
b.c_obu_new,
j.c_tar,
j.c_naz,
C.c_pos,
B.f_ric_obu_sat,
F.t_des,
a.d_ord,
DATE(G.d_ape_pro),
DATE(G.d_chiu_pro),
DATE(G.d_com_con),
DATE(C.d_spe_spe),
C.c_ide_spe,
DATE(H.d_acq_con)
Avoid using functions on table columns in where clause. Also, check whether "group by" is necessary as suggested by #jarlh
If d_ord is timestamp column, change where clause to
a.d_ord < timestamp( CURRENT_DATE + 1 days)
AND a.d_ord >= timestamp( CURRENT_DATE - 30 DAYS )

How can i optimize this oracle query?

i'm working with oracle 11g and we have a problem, well, this query takes forever to execute, the main table tbl_inc has about 17 million records, is there any way i can improve this query?
i can't add indexes, i don't have privileges for that.
SELECT count(*) FROM TBL_INC INC LEFT JOIN TBL_PDS P ON INC.SID = P.TRX
INNER JOIN TBL_ASTS ASTS ON ASTS.CODE = INC.CODE AND ASTS.MIT
= INC.MIT AND ASTS.OPE_PROD = 3
WHERE (INC.INC_DATE -1) >= to_date('29/10/20', 'DD/MM/YY')
AND INC.INC_DATE - 1 <= to_date('05/11/20', 'DD/MM/YY')
AND INC.OPE = 50 AND SUBSTR(INC.CARD_NMBR, 1, 6) = 123456
AND INC.MIT='05' AND INC.CODE='00';
thanks
First, I would rewrite this so the where clause does not have expressions on the columns:
SELECT count(*)
FROM TBL_INC INC LEFT JOIN
TBL_PDS P
ON INC.SID = P.TRX INNER JOIN
TBL_ASTS ASTS
ON ASTS.CODE = INC.CODE AND
ASTS.MIT = INC.MIT AND
ASTS.OPE_PROD = 3
WHERE INC.INC_DATE >= to_date('29/10/20', 'DD/MM/YY') + interval '1 day' AND
AND INC.INC_DATE - 1 <= to_date('05/11/20', 'DD/MM/YY') + interval '1 day' AND
INC.OPE = 50 AND
INC.CARD_NMBR LIKE '123456%' AND
INC.MIT = '05' AND INC.CODE = '00';
Then for this query, you want an index on: TBL_INC(MIT, CODE, OPE, INC_DATE, CARD_NMBR). I am guessing that you have indexes on the JOIN keys used in the other tables, but those would be TBL_PDS(TRX) and TBL_ASTS(CODE< MIT, OPE_PROD).
It is a very good practice to reduce the number of the rows from the join, rather that apply a 'where' condition to the end
SELECT count(1) FROM TBL_INC INC
INNER JOIN TBL_ASTS ASTS
ON ASTS.CODE = INC.CODE
AND ASTS.MIT = INC.MIT
AND ASTS.OPE_PROD = 3
AND INC.OPE = 50
AND SUBSTR(INC.CARD_NMBR, 1, 6) = 123456
AND INC.MIT='05'
AND INC.CODE='00'
AND (INC.INC_DATE -1) >= to_date('29/10/20', 'DD/MM/YY')
AND INC.INC_DATE - 1 <= to_date('05/11/20', 'DD/MM/YY')
LEFT JOIN
TBL_PDS P
ON INC.SID = P.TRX

The right order of join - build up a new query

So I have 2 working sub-queries:
Query #1:
select aa.kod_id, aa.rid_ct_a, aa.dodavatel
from
(select pl.dodavatel, po.kod_id, po.rid_ct_a
from prijemky_list pl
join prijemky_obsah po on pl.rid = po.rid_o
where pl.datum_p >= trunc(sysdate) - 365
and pl.dodavatel not in (100, 330, 522)
and pl.storno = 0
and not exists (select 1
from prijemky_list pl
join kody_oper on skratka = pl.kod_o
where id_cis = 3 and typ_skl_poh = 8)
group by
pl.dodavatel, po.kod_id, po.rid_ct_a, pl.datum_p
order by
pl.datum_p desc) aa
Query #2:
select bb.partner, bb.kod_id, bb.cislo_e, bb.rid_obj
from
(select ll.partner, o.kod_id, o.rid_obj, ll.cislo_e
from ct_l l
join ct_o o on l.rid = o.rid_o
join ct_l ll on substr(l.cislo_e, 1, 5) = ll.cislo_e) bb
I want to create a new query with a LEFT JOIN:
NVL((select decode(op.blizsia_spec, null, 'COOP AKCIA', op.blizsia_spec)||' /'||cislo_e from (
--**FIRST QUERY**
LEFT JOIN
--**SECOND QUERY**
ON aa.dodavatel=bb.partner and bb.kod_id=aa.kod_id bb.rid_obj=aa.rid_ct_a )
cc
JOIN obch_partneri op ON cc.partner = op.id
where rownum = 1),'bežný nákup')
But I get an error:
invalid identifier
Can somebody build up this query correctly?
To me, it looks like
WITH
tfirst AS (SELECT whatever FROM first_query),
tsecond AS (SELECT whatever FROM second_query)
SELECT NVL (
DECODE (op.blizsia_spec, NULL, 'COOP AKCIA', op.blizsia_spec)
|| ' /'
|| cislo_e,
'bežný nákup') result
FROM tfirst aa
LEFT JOIN tsecond bb
ON aa.dodavatel = bb.partner
AND bb.kod_id = aa.kod_id
AND bb.rid_obj = aa.rid_ct_a
JOIN obch_partneri op ON bb.partner = op.id

create an classification for months ordered

I'm trying to create an column in my query to show an ordered classification ( show 1, 2, 3 ( as in first, second, third ...)) relative to date... in my current query i have filtered data from the last 12 months ( as example, from 1-9-2016 to 31-8-2017)
using DATEADD(mm; DATEDIFF(m; - 1; GETDATE()) - 12; 0)
for the first date and
DATEADD(s; - 1; DATEADD(mm; DATEDIFF(m; 0; GETDATE()) + 1; 0))
for the last day of the current month. And i also have two columns, one with the month and other with the year, both extracted from a document date column present in the data ( i'm using
MONTH(dbo.Mov_Venda_Cab.dtmData) and YEAR(dbo.Mov_Venda_Cab.dtmData)).
My goal is to have a column showing something like this :
If the month is the first from the interval ( if is month 9 and year 2016 ) is has to show 1 , if is the second ( month 10 and year 2016) , show 2, all continuously until the current month ( that is 8 and year 2017) and showing 12.
If the values where static i could do a simple case and would achieve what i wanted. My problem is that since when i get the data filtered by my current date and the 12 months behind, i don't manage to get the same result because i don't know exactly what i should do in the CASE expression.
so that it could help my columns are :
Item ; Qty ; Month ; Year ; dtmData ; orderedMonth
ORIGINAL QUERY :
SELECT DISTINCT DATEADD(mm, DATEDIFF(m, - 1, GETDATE()) - 12, 0) AS DATA_INI,
DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) + 1, 0)) AS DATA_FIM,
dbo.Mov_Venda_Lin.Id,
MONTH(dbo.Mov_Venda_Cab.dtmData) AS Mes,
YEAR(dbo.Mov_Venda_Cab.dtmData) AS Ano,
dbo.Mov_Venda_Lin.fltValorMercadoriaSIVA * dbo.Mov_Venda_Cab.intSinal AS Mercadoria,
dbo.Mov_Venda_Lin.fltValorLiquido * dbo.Mov_Venda_Cab.intSinal AS ValorLiquido,
CASE
WHEN tbl_tipos_documentos.bitconsideraqtdmapas = 1
THEN (Mov_Venda_Lin.fltQuantidade * mov_venda_cab.intsinal)
ELSE 0
END AS Quantidade,
dbo.Mov_Venda_Lin.strCodSeccao AS Seccao,
dbo.Mov_Venda_Lin.strAbrevTpDoc AS TpDoc,
dbo.Tbl_Tipos_Documentos.strDescricao AS DescTpDoc,
dbo.Mov_Venda_Lin.intNumLinha AS Linha,
dbo.Mov_Venda_Lin.strCodExercicio AS Exercicio,
dbo.Mov_Venda_Cab.strAbrevMoeda AS Moeda,
dbo.Mov_Venda_Cab.fltCambio AS Cambio,
dbo.Mov_Venda_Lin.strCodArtigo AS Artigo,
dbo.Tbl_Gce_Artigos.strDescricao AS DescArtigo,
dbo.Mov_Venda_Lin.strCodClassMovStk AS MovStk,
dbo.Tbl_ClassificacaoMovStk.strDescricao AS DescMovStk,
CASE
WHEN mov_venda_cab.inttpentidade = 0
THEN tbl_gce_tipos_entidade.strcodigo
ELSE NULL
END AS TpEntidade,
CASE
WHEN mov_venda_cab.inttpentidade = 0
THEN tbl_gce_tipos_entidade.strdescricao
ELSE NULL
END AS DescTpEntidade,
CASE
WHEN mov_venda_cab.intcodentidade <> 0
THEN mov_venda_cab.intcodentidade
ELSE NULL
END AS CodEntidade,
CASE
WHEN mov_venda_cab.inttpentidade = 0
AND mov_venda_cab.intcodentidade <> 0
THEN 'Cliente'
WHEN mov_venda_cab.inttpentidade = 1
AND mov_venda_cab.intcodentidade <> 0
THEN 'Outro Devedor'
ELSE NULL
END AS TipoEntidade,
CASE
WHEN mov_venda_cab.inttpentidade = 0
THEN tbl_clientes.strnome
ELSE tbl_outros_devedores.strnome
END AS DescNome,
dbo.Tbl_SubZonas.strAbrevZona AS Zona,
dbo.Tbl_Zonas.strDescricao AS DescZona,
dbo.Mov_Venda_Cab.strAbrevSubZona AS SubZona,
dbo.Tbl_SubZonas.strDescricao AS DescSubZona,
dbo.Mov_Venda_Cab.intCodVendedor AS Vendedor,
dbo.Tbl_Gce_Vendedores.strNome AS DescNomeVend,
dbo.Tbl_Gce_Artigos.strCodCategoria AS Categoria,
dbo.Tbl_Gce_Categorias.strDescricao AS DescCategoria,
dbo.Tbl_Gce_Artigos.strTpArtigo AS TpArtigo,
dbo.Tbl_Gce_Tipos_Artigos.strDescricao AS DescTpArtigo,
CAST(NULL AS VARCHAR(13)) AS CodFamiliaAgrup,
CAST(NULL AS VARCHAR(35)) AS DescFamAgrup,
CAST(NULL AS VARCHAR(13)) AS CodFamiliaRes,
CAST(NULL AS VARCHAR(35)) AS DescFamRes,
dbo.Mov_Venda_Cab.strForteAbrevMoeda AS abrevmoeda,
dbo.Mov_Venda_Cab.fltForteCambio AS fortecambio
FROM dbo.Mov_Venda_Lin WITH (NOLOCK)
LEFT OUTER JOIN dbo.Mov_Venda_Cab WITH (NOLOCK)
ON dbo.Mov_Venda_Lin.strCodSeccao = dbo.Mov_Venda_Cab.strCodSeccao
AND dbo.Mov_Venda_Lin.strAbrevTpDoc = dbo.Mov_Venda_Cab.strAbrevTpDoc
AND dbo.Mov_Venda_Lin.strCodExercicio = dbo.Mov_Venda_Cab.strCodExercicio
AND dbo.Mov_Venda_Lin.intNumero = dbo.Mov_Venda_Cab.intNumero
LEFT OUTER JOIN dbo.Tbl_Gce_Armazens WITH (NOLOCK)
ON dbo.Mov_Venda_Lin.strCodArmazem = dbo.Tbl_Gce_Armazens.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Artigos WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Mov_Venda_Lin.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_ArtigosFamilias WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Tbl_Gce_ArtigosFamilias.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_Familias WITH (NOLOCK)
ON dbo.Tbl_Gce_ArtigosFamilias.strCodFamilia = dbo.Tbl_Gce_Familias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_ArtigosReferencias WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodigo = dbo.Tbl_Gce_ArtigosReferencias.strCodArtigo
LEFT OUTER JOIN dbo.Tbl_Gce_Referencias WITH (NOLOCK)
ON dbo.Tbl_Gce_ArtigosReferencias.strCodReferencia = dbo.Tbl_Gce_Referencias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Tipos_Artigos WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strTpArtigo = dbo.Tbl_Gce_Tipos_Artigos.strCodigo
LEFT OUTER JOIN dbo.Tbl_Clientes WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Clientes.intCodigo
LEFT OUTER JOIN dbo.Tbl_Direccoes WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Direccoes.intCodigo
AND dbo.Mov_Venda_Cab.intDireccao = dbo.Tbl_Direccoes.intNumero
AND dbo.Mov_Venda_Cab.intTpEntidade = dbo.Tbl_Direccoes.intTp_Entidade
LEFT OUTER JOIN dbo.Tbl_Outros_Devedores WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodEntidade = dbo.Tbl_Outros_Devedores.intCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Vendedores WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.intCodVendedor = dbo.Tbl_Gce_Vendedores.intCodigo
LEFT OUTER JOIN dbo.Tbl_Tipos_Documentos WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.strAbrevTpDoc = dbo.Tbl_Tipos_Documentos.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_SubZonas WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.strAbrevSubZona = dbo.Tbl_SubZonas.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_Zonas WITH (NOLOCK)
ON dbo.Tbl_SubZonas.strAbrevZona = dbo.Tbl_Zonas.strAbreviatura
LEFT OUTER JOIN dbo.Tbl_Gce_Categorias WITH (NOLOCK)
ON dbo.Tbl_Gce_Artigos.strCodCategoria = dbo.Tbl_Gce_Categorias.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Seccoes WITH (NOLOCK)
ON dbo.Mov_Venda_Cab.strCodSeccao = dbo.Tbl_Gce_Seccoes.strCodigo
LEFT OUTER JOIN dbo.Tbl_Gce_Tipos_Entidade WITH (NOLOCK)
ON dbo.Tbl_Clientes.strTpEntidade = dbo.Tbl_Gce_Tipos_Entidade.strCodigo
LEFT OUTER JOIN dbo.Tbl_ClassificacaoMovStk WITH (NOLOCK)
ON dbo.Mov_Venda_Lin.strCodClassMovStk = dbo.Tbl_ClassificacaoMovStk.strCodigo
WHERE (dbo.Mov_Venda_Cab.intTpEntidade = 0
OR dbo.Mov_Venda_Cab.intTpEntidade IS NULL)
AND (dbo.Mov_Venda_Cab.strAbrevTpDoc IN ('CRFCX', 'FACIV', 'FACTC', 'FCTA', 'LANIV', 'LOFX', 'LONC', 'LXANI', 'NCFCX', 'NFACC', 'NFACE', 'NFACM', 'NFACT', 'NNCRC', 'NNCRE', 'NNCRM', 'NNDEB', 'NNDEC', 'NNDEV', 'NVDIC', 'NVDIN', 'XLACC', 'XLACD'))
AND (dbo.Mov_Venda_Cab.strCodSeccao IN ('1', 'ENCT1', 'ENCT2', 'ENCT3', 'ENCT4', 'ENCT5', 'ENCT6'))
AND (dbo.Mov_Venda_Cab.dtmData > DATEADD(mm, DATEDIFF(m, - 1, GETDATE()) - 12, 0))
AND (dbo.Mov_Venda_Cab.dtmData <= DATEADD(s, - 1, DATEADD(mm, DATEDIFF(m, 0, GETDATE()) + 1, 0)))
AND (dbo.Mov_Venda_Lin.intTpLinha > 2)
AND (dbo.Mov_Venda_Cab.bitAnulado = 0)
AND (dbo.Mov_Venda_Cab.bitConvertido = 0)
Luckily there's a much less complicated method than using a bunch of CASE statements. You can use the ROW_NUMBER function.
First, don't split your dates into month and year. Just use Getdate() to calculate your desired range and compare your source dates to that. Then you add the ROW_NUMBER to get your ordering output:
SELECT
*
,ordered_output = (ROW_NUMBER()OVER(PARTITION BY grouping_field ORDER BY cast(dtmData as datetime) ASC))
FROM Mov_Venda_Cab
WHERE cast(dtmData as datetime) >= getdate() - 365
This example assumes your have some ID field or similar on which your want to group your output, represented by grouping_field in the example. Your results would look like:
grouping_field dtmData ordered_output
1 8/1/2017 1
1 8/2/2017 2
1 8/3/2017 3
2 8/1/2017 1
2 8/2/2017 2
2 8/3/2017 3
If you don't want to group your output, just ordering everything by the date, you can omit the PARTITION BY grouping_field text. You'd get instead something like:
dtmData ordered_output
8/1/2017 1
8/2/2017 2
8/3/2017 3
8/4/2017 4
8/5/2017 5
8/6/2017 6
EDIT: Asker clarified that all records with the same month should get the same ordered output.
To do that you first need to assign each month/year combo a rank and rejoin that to the main table using two layers of subqueries:
SELECT b.*, c.month_rank
from Mov_Venda_Cab as b
inner join
(select mnt, yr, ROW_NUMBER() OVER(ORDER BY A.yr, A.mnt) AS month_rank
from (
SELECT DISTINCT
MONTH(dtmData) as mnt
, YEAR(dtmData) as yr
from Mov_Venda_Cab
WHERE cast(dtmData as datetime) >= getdate() - 365
) as a
) as c
on MONTH(b.dtmData) = c.mnt and YEAR(b.dtmData) = c.yr

I need help in getting an Oracle SQL Query optimized to run for a longer time period

#DRapp - Revised query below: I need help in optimizing a Oracle/SQL query to run for more than 2 weeks of data. it works for 2 weeks of data then chokes. I inherited this. All the business rules need to stay, but is there a way I can simplify this so it will work for a larger data set? Specific examples and tips would be appreciated. This can be broken down into several queries, but needs to return the same results back. thanks for your help.
Oracle SQL Query code is as follows:
SELECT '1' AS group1,
usr.USR_NAME,
rec.USR_UID_USER,
rec.REC_DATE_PAID,
TO_CHAR(rec.REC_DATE_PAID, 'MM/DD/YYYY (fmDay)') AS group_date,
rec.REC_AMOUNT,
rec.REC_UID,
rec.REG_UID_RECEIPT_GROUP,
rec.REC_TAX1_AMOUNT,
rec.REC_TAX2_AMOUNT,
rec.REC_TAX3_AMOUNT,
rec.REC_AMOUNT - (
CASE
WHEN NVL2(dis.SUMDIS, dis.SUMDIS, 0) <> 0
THEN NVL(Fit2Sum.SumAmt, 0)
ELSE 0
END) - rec.REC_TAX1_AMOUNT - rec.REC_TAX2_AMOUNT - rec.REC_TAX3_AMOUNT
AS "GrossRevAmountnoTax",
rec.REC_AMOUNT,
-(
CASE
WHEN NVL2(dis.SUMDIS, dis.SUMDIS, 0) <> 0
THEN NVL(Fit2Sum.SumAmt, 0)
ELSE 0
END)
AS "GrossRevAmountwTax",
rec.REC_AMOUNT - rec.REC_TAX1_AMOUNT - rec.REC_TAX2_AMOUNT - rec.REC_TAX3_AMOUNT
AS "NetRevenueAmount",
(
CASE
WHEN NVL(FitGrace.GraceAmount, 0) = 0
THEN 1
ELSE 0
END) AS "IsGrace",
(
CASE
WHEN NVL(dis.DIS_UID, 0) = 10
THEN NVL(dis.SUMDIS, 0)
ELSE 0
END) AS "TicoAmount",
(
CASE
WHEN NVL(dis.DIS_UID, 0) = 10
THEN 1
ELSE 0
END) AS "TicoCount",
(
CASE
WHEN NVL(dis.DIS_UID, 0) NOT IN (10, 0)
THEN NVL(dis.SUMDIS, 0)
ELSE 0
END) AS "ValidationAmount",
(
CASE
WHEN NVL(dis.DIS_UID, 0) NOT IN (10, 0)
THEN 1
ELSE 0
END) AS "ValidationCount",
(
CASE
WHEN NVL(PRFGrp.PSMCount, 0) > 1
THEN 'Central Cashier Station'
ELSE TO_CHAR(PRFGrp.MaxFacDescription)
END) AS "FacilityDescription",
(
CASE
WHEN NVL(PRFGrp.PSMCount, 0) > 1
THEN 0
ELSE MAX(PRFGrp.FAC_UID_FACILITY)
END) AS "FacilityUID",
dis.DIS_DESCRIPTION "DiscountDescription",
NVL(dis.countdis, 0) "ValCount",
NVL(dis.SUMDIS, 0) "ValAmount",
NVL(dis.DIS_UID, 0) "DiscountUID",
dis.VLDNUM "ValidationNumber",
dis.THI_NAME "ValidationThirdParty",
dis.VTE_DESCRIPTION "ValidationControlGroup",
pmm.PMM_DESCRIPTION,
pmm.PMM_UID,
pmm.PAY_UID_PAYMENT_TYPE,
psm.PSM_DESCRIPTION,
pol.POL_DESCRIPTION,
cas.CAS_UID,
cas.CAS_OPEN_DATE,
cas.CAS_CLOSE_DATE,
MAX(fit.FIT_SALE_ITEM_DESCRIPTION) AS SaleItem,
NVL(per.PER_NUMBER, rtx.RTX_REPLACEMENT_NUMBER) AS TicketNumber,
rtx.RTX_REPLACEMENT_NUMBER AS ReplacementNumber,
NVL(ptx.PTX_DATE_ENTRY, ptx2.PTX_DATE_ENTRY) AS "EntryTime",
NVL(ptx.PTX_DATE_EXIT, ptx2.PTX_DATE_EXIT) AS "ExitTime",
(TO_CHAR(TRUNC(NVL(ptx.PTX_DATE_EXIT, ptx2.PTX_DATE_EXIT) - NVL(ptx.PTX_DATE_ENTRY,
ptx2.PTX_DATE_ENTRY)))
|| 'd '
|| TO_CHAR(mod(TRUNC((NVL(ptx.PTX_DATE_EXIT, ptx2.PTX_DATE_EXIT) - NVL(ptx.PTX_DATE_ENTRY,
ptx2.PTX_DATE_ENTRY)) * 24), 24))
|| 'h '
|| TO_CHAR(mod(TRUNC((NVL(ptx.PTX_DATE_EXIT, ptx2.PTX_DATE_EXIT) - NVL(ptx.PTX_DATE_ENTRY,
ptx2.PTX_DATE_ENTRY)) * 24 * 60), 60))
|| 'm '
|| TO_CHAR(mod(TRUNC((NVL(ptx.PTX_DATE_EXIT, ptx2.PTX_DATE_EXIT) - NVL(ptx.PTX_DATE_ENTRY,
ptx2.PTX_DATE_ENTRY)) * 24 * 60 * 60), 60))
|| 's') AS "TimeElapsed",
NVL(ptx.LAN_UID_ENTRY, ptx2.LAN_UID_ENTRY) AS "EntryLaneUID",
NVL(ptx.LAN_UID_EXIT, ptx2.LAN_UID_EXIT) AS "ExitLaneUID",
MAX(
(SELECT lan.LAN_DESCRIPTION
FROM lane lan
WHERE lan.LAN_UID = NVL(ptx.LAN_UID_ENTRY, ptx2.LAN_UID_ENTRY)
)) AS "EntryLaneDesc",
MAX(
(SELECT lan.LAN_DESCRIPTION
FROM lane lan
WHERE lan.LAN_UID = NVL(ptx.LAN_UID_EXIT, ptx2.LAN_UID_EXIT)
)) AS "ExitLaneDesc",
crc.CRC_LAST_FOUR,
ctr.CTR_CONFIRMATION_CODE,
ctr.CTR_RETURN_CODE,
ctr.CTR_RETURN_MESSAGE,
ctr.CTR_TRAN_GUID,
ctr.CTR_AUTHORIZATION_REQUEST_DATE,
ctr.CTR_SUCCESS,
ctr.CTR_TRANSACTION_DATE
FROM RECEIPT rec
INNER JOIN USER_ACCOUNT usr
ON rec.USR_UID_USER = usr.USR_UID
INNER JOIN PAYMENT_METHOD_MLKP pmm
ON rec.PMM_UID_PAYMENT_METHOD = pmm.PMM_UID
INNER JOIN financial_transaction fit
ON rec.REC_UID = fit.REC_UID_RECEIPT
LEFT JOIN permission per
ON fit.FIT_SOURCE_OBJ_UID = per.PER_UID
AND fit.TAB_UID_SOURCE_OBJ_TYPE = 10
LEFT JOIN parking_transaction ptx
ON per.PER_UID = ptx.PER_UID_PERMISSION
AND ptx.PTT_UID_TYPE <> 17
LEFT JOIN replacement_transaction rtx
ON fit.FIT_SOURCE_OBJ_UID = rtx.RTX_UID
AND fit.TAB_UID_SOURCE_OBJ_TYPE = 332
LEFT JOIN parking_transaction ptx2
ON rtx.RTX_UID = ptx2.RTX_UID_REPLACEMENT_TRANS
AND ptx.PTT_UID_TYPE <> 17
LEFT JOIN
(SELECT dis.DIS_DESCRIPTION,
dis.DIS_UID,
vte.VTE_DESCRIPTION,
fit2.FIT_UID AS countdis,
fit2.FIT_AMOUNT AS SUMDIS,
vld.VLD_VALIDATION_NUMBER AS VLDNUM,
thi.THI_NAME,
fit2.FIT_UID_PAY_ADJ_REV_ITEM
FROM financial_transaction fit2
INNER JOIN discount_mlkp dis
ON fit2.DIS_UID_DISCOUNT = dis.DIS_UID
LEFT JOIN validation vld
ON fit2.VLD_UID_VALIDATION = vld.VLD_UID
LEFT JOIN enc_print_history esp
ON vld.ESP_UID_PRINT_ID = esp.ESP_UID
LEFT JOIN third_party thi
ON esp.THI_UID_THIRD_PARTY = thi.THI_UID
LEFT JOIN validation_control_group vte
ON vld.VTE_UID_VALIDATION_CTRL_GRP = vte.VTE_UID
WHERE fit2.DIS_UID_DISCOUNT <> 0
) dis ON fit.FIT_UID_PAY_ADJ_REV_ITEM = dis.FIT_UID_PAY_ADJ_REV_ITEM
AND rec.REC_UID =
(SELECT MIN(rec2.REC_UID)
FROM receipt rec2
INNER JOIN receipt_group reg
ON rec2.REG_UID_RECEIPT_GROUP = reg.REG_UID
WHERE rec.REG_UID_RECEIPT_GROUP = reg.REG_UID
)
LEFT JOIN
(SELECT fit2.FIT_UID_PAY_ADJ_REV_ITEM,
SUM(fit2.FIT_AMOUNT) AS SumAmt
FROM financial_transaction fit2
WHERE fit2.DIS_UID_DISCOUNT <> 0
GROUP BY fit2.FIT_UID_PAY_ADJ_REV_ITEM
) Fit2Sum
ON fit.FIT_UID_PAY_ADJ_REV_ITEM = Fit2Sum.FIT_UID_PAY_ADJ_REV_ITEM
LEFT JOIN
(SELECT fit2.FIT_UID,
SUM(fit2.FIT_AMOUNT) AS GraceAmount
FROM financial_transaction fit2
GROUP BY fit2.FIT_UID
) FitGrace
ON fit.FIT_UID_PAY_ADJ_REV_ITEM = FitGrace.FIT_UID
INNER JOIN cashdrawer_session cas
ON rec.CAS_UID_CASHDRAWER_SESSION = cas.CAS_UID
INNER JOIN pos_station psm
ON cas.PSM_UID_STATION = psm.PSM_UID
INNER JOIN pos_station_type_lkp pol
ON psm.POL_UID_STATION_TYPE = pol.POL_UID
LEFT JOIN
(SELECT pfr.PSM_UID_STATION,
COUNT(*) AS PSMCount,
MAX(fac.FAC_DESCRIPTION) AS MaxFacDescription,
pfr.FAC_UID_FACILITY
FROM pos_facility_rel pfr
INNER JOIN facility fac
ON pfr.FAC_UID_FACILITY = fac.FAC_UID
GROUP BY pfr.PSM_UID_STATION,
pfr.FAC_UID_FACILITY
) PRFGrp ON psm.PSM_UID = PRFGrp.PSM_UID_STATION
LEFT JOIN ctr_rec_rel crr
ON rec.REC_UID = crr.REC_UID_RECEIPT
LEFT JOIN credit_card_transaction ctr
ON crr.CTR_UID_CREDIT_CARD_TRANS = ctr.CTR_UID
LEFT JOIN credit_card crc
ON ctr.CRC_UID_PROCESSED = crc.CRC_UID
WHERE pmm.PMM_UID <> 12
GROUP BY usr.USR_NAME,
rec.USR_UID_USER,
rec.REC_DATE_PAID,
TO_CHAR(rec.REC_DATE_PAID, 'MM/DD/YYYY (fmDay)'),
rec.REC_AMOUNT,
rec.REC_UID,
rec.REG_UID_RECEIPT_GROUP,
rec.REC_TAX1_AMOUNT,
rec.REC_TAX2_AMOUNT,
rec.REC_TAX3_AMOUNT,
dis.DIS_DESCRIPTION,
dis.VLDNUM,
dis.THI_NAME,
dis.VTE_DESCRIPTION,
pmm.PMM_DESCRIPTION,
pmm.PMM_UID,
pmm.PAY_UID_PAYMENT_TYPE,
psm.PSM_DESCRIPTION,
pol.POL_DESCRIPTION,
cas.CAS_UID,
cas.CAS_OPEN_DATE,
cas.CAS_CLOSE_DATE,
NVL(per.PER_NUMBER, rtx.RTX_REPLACEMENT_NUMBER),
rtx.RTX_REPLACEMENT_NUMBER,
NVL(ptx.PTX_DATE_ENTRY, ptx2.PTX_DATE_ENTRY),
NVL(ptx.PTX_DATE_EXIT, ptx2.PTX_DATE_EXIT),
NVL(ptx.LAN_UID_ENTRY, ptx2.LAN_UID_ENTRY),
NVL(ptx.LAN_UID_EXIT, ptx2.LAN_UID_EXIT),
crc.CRC_LAST_FOUR,
ctr.CTR_CONFIRMATION_CODE,
ctr.CTR_RETURN_CODE,
ctr.CTR_RETURN_MESSAGE,
ctr.CTR_TRAN_GUID,
ctr.CTR_AUTHORIZATION_REQUEST_DATE,
ctr.CTR_SUCCESS,
ctr.CTR_TRANSACTION_DATE,
fit.FIT_UID_PAY_ADJ_REV_ITEM,
dis.countdis,
dis.SUMDIS,
dis.DIS_UID,
psm.PSM_UID,
(rec.REC_AMOUNT - rec.REC_TAX1_AMOUNT - rec.REC_TAX2_AMOUNT - rec.REC_TAX3_AMOUNT)
If you see a step change in performance (rather than just a linear change in query duration relative to the date range), it's likely to be due to one of three issues:
A change in the query optimisation, which you can check with an execution plan. http://docs.oracle.com/cd/E11882_01/appdev.112/e25788/d_xplan.htm
An increase in the data volume causing a sort operation to switch from optimal to one-pass, or from one-pass to multipass, which you can check by using v$sql_workarea http://docs.oracle.com/cd/E11882_01/server.112/e40402/dynviews_3061.htm#REFRN30256
A change in the "rate" of data -- for example, if you went from 10,000 records per day to 50,000.
These would be the first issues I'd check.
Aside from cleaning (format) of the query to see better what is going on, I made a few small changes. You had a few columns that were based on select count(*) or similar based on whatever the current "fit" record was. From the sounds of your data, that is killing the system some. I've moved those out to three separate LEFT-JOINs to the respective tables (Fit2Sum and FitGrace linked to FIT, and PRFGrp is linked via psm alias).
Now, that said, and I dont know how large volume your tables are, you MAY want to put some limit if there are any date/time fields there that you can restrict (such as only for a month of data...). But, by pre-querying those vs being done on every record COULD be an impact that is killing your process.
SELECT
'1' AS group1,
usr.USR_NAME,
rec.USR_UID_USER,
rec.REC_DATE_PAID,
TO_CHAR(rec.rec_date_paid,'MM/DD/YYYY (fmDay)') AS group_date,
rec.rec_amount,
rec.rec_uid,
rec.reg_uid_receipt_group,
rec.rec_tax1_amount,
rec.rec_tax2_amount,
rec.rec_tax3_amount,
MAX( rec.rec_amount -
- CASE WHEN NVL2( dis.sumdis, dis.sumdis,0) <> 0
THEN NVL( Fit2Sum.SumAmt, 0 )
ELSE 0 END
- rec.rec_tax1_amount
- rec.rec_tax2_amount
- rec.rec_tax3_amount ) AS "GrossRevAmountNoTax",
MAX( rec.rec_amount
- CASE WHEN NVL2(dis.sumdis,dis.sumdis,0) <> 0
THEN NVL( Fit2Sum.SumAmt, 0 )
ELSE 0 END ) AS "GrossRevAmountwTax",
MAX( rec.REC_AMOUNT
- rec.rec_tax1_amount
- rec.rec_tax2_amount
- rec.rec_tax3_amount ) AS "NetRevenueAmount",
MAX( CASE WHEN NVL( FitGrace.GraceAmount, 0 ) = 0
THEN 1
ELSE 0 END) AS "IsGrace",
/*Grace tickets have original fee amount of 0*/
MAX( CASE WHEN NVL(dis.dis_uid,0) = 10
THEN NVL(dis.sumdis,0)
ELSE 0 END ) AS "TicoAmount",
/*dis_uid = 10 is TICO*/
MAX( CASE WHEN NVL(dis.dis_uid,0) = 10
THEN 1
ELSE 0 END ) AS "TicoCount",
MAX( CASE WHEN NVL(dis.dis_uid,0) NOT IN (10,0)
THEN NVL(dis.sumdis,0)
ELSE 0 END ) AS "ValidationAmount",
MAX( CASE WHEN NVL(dis.dis_uid,0) NOT IN (10,0)
THEN 1
ELSE 0 END ) AS "ValidationCount",
MAX( CASE WHEN NVL( PRFGrp.PSMCount, 0 ) > 1
THEN 'Central Cashier Station'
ELSE TO_CHAR(PRFGrp.MaxFacDescription) END ) AS "FacilityDescription",
/*pulls the facility description or Central Cashier Station if a central cashier station*/
MAX( CASE WHEN NVL( PRFGrp.PSMCount, 0 ) > 1
THEN 0
ELSE MAX(PRFGrp.fac_uid_facility) END ) AS "FacilityUID",
dis.dis_description "DiscountDescription",
NVL(dis.countdis,0) "ValCount",
NVL(dis.sumdis,0) "ValAmount",
NVL(dis.dis_uid,0) "DiscountUID",
dis.VLDNUM "ValidationNumber",
dis.thi_name "ValidationThirdParty",
dis.vte_description "ValidationControlGroup",
pmm.PMM_DESCRIPTION,
pmm.pmm_uid,
pmm.pay_uid_payment_type,
psm.psm_description,
pol.pol_description,
cas.cas_uid,
cas.cas_open_date,
cas.cas_close_date,
MAX(fit.fit_sale_item_description) AS SaleItem,
NVL(per.per_number, rtx.rtx_replacement_number) AS TicketNumber,
rtx.rtx_replacement_number AS ReplacementNumber,
NVL(ptx.ptx_date_entry, ptx2.ptx_date_entry) AS "EntryTime",
NVL(ptx.ptx_date_exit, ptx2.ptx_date_exit) AS "ExitTime",
MAX(( TO_CHAR( TRUNC( NVL(ptx.ptx_date_exit, ptx2.ptx_date_exit)
-NVL(ptx.ptx_date_entry, ptx2.ptx_date_entry)))||'d '||
TO_CHAR(mod(TRUNC(( NVL(ptx.ptx_date_exit, ptx2.ptx_date_exit)
-NVL(ptx.ptx_date_entry, ptx2.ptx_date_entry))*24),24))||'h '||
TO_CHAR(mod(TRUNC(( NVL(ptx.ptx_date_exit, ptx2.ptx_date_exit)
-NVL(ptx.ptx_date_entry, ptx2.ptx_date_entry))*24*60),60))||'m '||
TO_CHAR(mod(TRUNC(( NVL(ptx.ptx_date_exit,ptx2.ptx_date_exit)
-NVL(ptx.ptx_date_entry,ptx2.ptx_date_entry))*24*60*60),60))||'s')) AS "TimeElapsed",
/*pulls the time between entry/exit in DD HH MM SS format*/
NVL(ptx.lan_uid_entry, ptx2.lan_uid_entry) AS "EntryLaneUID",
NVL(ptx.lan_uid_exit, ptx2.lan_uid_exit) AS "ExitLaneUID",
MAX( ( SELECT lan.lan_description
FROM lane lan
WHERE lan.lan_uid = NVL(ptx.lan_uid_entry, ptx2.lan_uid_entry))) AS "EntryLaneDesc",
MAX( ( SELECT lan.lan_description
FROM lane lan
WHERE lan.lan_uid = NVL(ptx.lan_uid_exit, ptx2.lan_uid_exit))) AS "ExitLaneDesc",
crc.crc_last_four,
ctr.ctr_confirmation_code,
ctr.ctr_return_code,
ctr.ctr_return_message,
ctr.ctr_tran_guid,
ctr.ctr_authorization_request_date,
ctr.ctr_success,
ctr.ctr_transaction_date
FROM
RECEIPT rec
INNER JOIN USER_ACCOUNT usr
ON rec.USR_UID_USER = usr.USR_UID
INNER JOIN PAYMENT_METHOD_MLKP pmm
ON rec.PMM_UID_PAYMENT_METHOD = pmm.PMM_UID
INNER JOIN financial_transaction fit
ON rec.rec_uid = fit.rec_uid_receipt
LEFT JOIN permission per
ON fit.fit_source_obj_uid = per.per_uid
AND fit.tab_uid_source_obj_type = 10
LEFT JOIN parking_transaction ptx
ON per.per_uid = ptx.per_uid_permission
AND ptx.ptt_uid_type <> 17
LEFT JOIN replacement_transaction rtx
ON fit.fit_source_obj_uid = rtx.rtx_uid
AND fit.tab_uid_source_obj_type = 332
LEFT JOIN parking_transaction ptx2
ON rtx.rtx_uid = ptx2.rtx_uid_replacement_trans
AND ptx.ptt_uid_type <> 17
LEFT JOIN ( SELECT
dis.dis_description,
dis.dis_uid,
vte.vte_description,
fit2.fit_uid AS countdis,
fit2.fit_amount AS SUMDIS,
vld.vld_validation_number AS "VLDNUM",
thi.thi_name,
fit2.fit_uid_pay_adj_rev_item
FROM
financial_transaction fit2
INNER JOIN discount_mlkp dis
ON fit2.dis_uid_discount = dis.dis_uid
LEFT JOIN validation vld
ON fit2.vld_uid_validation = vld.vld_uid
LEFT JOIN enc_print_history esp
ON vld.esp_uid_print_id = esp.esp_uid
LEFT JOIN third_party thi
ON esp.thi_uid_third_party = thi.thi_uid
LEFT JOIN validation_control_group vte
ON vld.vte_uid_validation_ctrl_grp = vte.vte_uid
WHERE
fit2.dis_uid_discount <> 0) dis
ON fit.fit_uid_pay_adj_rev_item = dis.fit_uid_pay_adj_rev_item
AND rec.rec_uid = ( SELECT MIN(rec2.rec_uid)
FROM receipt rec2
INNER JOIN receipt_group reg
ON rec2.reg_uid_receipt_group = reg.reg_uid
WHERE rec.reg_uid_receipt_group = reg.reg_uid)
/*
this is grabbing the detail of any validations used during the transaction. If more then one
validation is used per transient, it will pull the transient permit record multiple times
(equal to the number of validations used). This is by design so we can get the detail info,
must account for these potential duplicates within report using running totals- Added logic to
account for split payments, case statement forces the validation info to only show for the
first receipt of the receipt group- JB21213
*/
LEFT JOIN ( select
fit2.fit_uid_pay_adj_rev_item,
SUM( fit2.fit_amount ) as SumAmt
from
financial_transaction fit2
where
fit2.dis_uid_discount <> 0
group by
fit2.fit_uid_pay_adj_rev_item ) Fit2Sum
ON fit.fit_uid_pay_adj_rev_item = Fit2Sum.fit_uid_pay_adj_rev_item
LEFT JOIN ( SELECT
fit2.fit_uid,
SUM(fit2.fit_amount) as GraceAmount
FROM
financial_transaction fit2
GROUP BY
fit2.fit_uid ) FitGrace
ON fit.fit_uid_pay_adj_rev_item = FitGrace.fit_uid
INNER JOIN cashdrawer_session cas
ON rec.cas_uid_cashdrawer_session = cas.cas_uid
INNER JOIN pos_station psm
ON cas.psm_uid_station = psm.psm_uid
INNER JOIN pos_station_type_lkp pol
ON psm.pol_uid_station_type = pol.pol_uid
LEFT JOIN ( select
prf.psm_uid_station,
COUNT(*) as PSMCount,
MAX(fac.fac_description) as MaxFacDescription
from
pos_facility_rel pfr
INNER JOIN facility fac
ON pfr.fac_uid_facility = fac.fac_uid
group by
prf.psm_uid_station ) PRFGrp
ON psm.psm_uid = PRFGrp.psm_uid_station
LEFT JOIN ctr_rec_rel crr
ON rec.rec_uid = crr.rec_uid_receipt
LEFT JOIN credit_card_transaction ctr
ON crr.ctr_uid_credit_card_trans = ctr.ctr_uid
LEFT JOIN credit_card crc
ON ctr.crc_uid_processed = crc.crc_uid
WHERE
pmm.pmm_uid <> 12
GROUP BY
usr.USR_NAME,
rec.USR_UID_USER,
rec.REC_DATE_PAID,
rec.REC_AMOUNT,
rec.rec_tax1_amount,
rec.rec_tax2_amount,
rec.rec_tax3_amount,
pmm.PMM_DESCRIPTION,
rec.rec_uid,
rec.reg_uid_receipt_group,
psm.psm_description,
cas.cas_uid,
cas.cas_open_date,
cas.cas_close_date,
fit.fit_uid_pay_adj_rev_item,
dis.dis_description,
dis.countdis,
dis.sumdis,
dis.VLDNUM,
dis.dis_uid,
dis.thi_name,
dis.vte_description,
pmm.pay_uid_payment_type,
psm.psm_uid,
pol.pol_description,
pmm.pmm_uid,
TO_CHAR(rec.rec_date_paid,'MM/DD/YYYY (fmDay)'),
NVL(per.per_number,rtx.rtx_replacement_number),
rtx.rtx_replacement_number,
NVL(ptx.ptx_date_entry,ptx2.ptx_date_entry),
NVL(ptx.ptx_date_exit,ptx2.ptx_date_exit),
NVL(ptx.lan_uid_entry,ptx2.lan_uid_entry),
NVL(ptx.lan_uid_exit,ptx2.lan_uid_exit),
crc.crc_last_four,
ctr.ctr_confirmation_code,
ctr.ctr_return_code,
ctr.ctr_return_message,
ctr.ctr_tran_guid,
ctr.ctr_authorization_request_date,
ctr.ctr_success,
ctr.ctr_transaction_date,
(rec.rec_amount
- rec.rec_tax1_amount
- rec.rec_tax2_amount
- rec.rec_tax3_amount );
QUERY CLARIFICATION...
To help understand what is going on with the revised query. On several of the fields, you were running the same query multiple times getting a COUNT(*) based on whatever was the "current" ID, being some facility, person, whatever. If you do that query at the field level, it runs those queries EACH TIME per column, per row...
What I have done was to do a SINGLE pre-aggregation on each respective per facility, person, whatever for those other aliases (such as Fit2Sum, FitGrace, PRFGrp). While keeping the respective "ID" as the group by column in those result sets, the LEFT-JOIN points to one record in each respective set based on that JOIN criteria.
Now, the case/when construct. Since the pre-aggregations have already been performed, and the join is per the respective "ID" column, you no longer need the COUNT() for each column, just grab the final column name from the pre-aggregation query and test that. If the record is found and has a count, do the same as your original COUNT(). In some case, it would return an ID, others, return 0. So, for your example of "GrossRevAmountnoTax",
rec.rec_amount-(CASE WHEN NVL2(dis.sumdis,dis.sumdis,0) <> 0
THEN
(SELECT SUM(fit2.fit_amount)
FROM financial_transaction fit2
WHERE fit.fit_uid_pay_adj_rev_item = fit2.fit_uid_pay_adj_rev_item
AND fit2.dis_uid_discount <> 0)
ELSE 0
END)-rec.rec_tax1_amount-rec.rec_tax2_amount-rec.rec_tax3_amount
AS "GrossRevAmountnoTax",
you are selecting the sum() of the fit_amount based on the fit_uid_pay_adj_rev_item. Since I prequeried this into the Fit2Sum alias, the join is on the fit_uid_pay_adj_rev_item and am just grabbing that column (Fit2Sum.SumAmt) so the query does NOT have to be done repeatedly.
rec.rec_amount -
- CASE WHEN NVL2( dis.sumdis, dis.sumdis,0) <> 0
THEN NVL( Fit2Sum.SumAmt, 0 )
ELSE 0 END
- rec.rec_tax1_amount
- rec.rec_tax2_amount
- rec.rec_tax3_amount AS "GrossRevAmountnoTax",
Again, since it is already sitting at the record in Fit2Sum alias, it can immediately follow with
rec.rec_amount-(CASE WHEN NVL2(dis.sumdis,dis.sumdis,0) <> 0
THEN
(SELECT SUM(fit2.fit_amount)
FROM financial_transaction fit2
WHERE fit.fit_uid_pay_adj_rev_item = fit2.fit_uid_pay_adj_rev_item
AND fit2.dis_uid_discount <> 0)
ELSE 0
END) AS "GrossRevAmountwTax",
without having to requery the set yet again.
So, your issue with the PRFGrp.PSMCount is doing a similar thing. The alias PRFGrp was based on another table, column/condition and summation. The join has that available and SHOULD be visible to your query, not the "fit" alias as I originally had. So, please look at the alias references and final column names in case I missed something and hopefully this clarification makes more sense to you.
ADDITIONAL REVISIONS
The fields that have case/when that are not part of the group by expression are probably causing the failure as you should group by any and all non-aggregate columns in the returned set.
These include GrossRevAmountNoTax, NetRevenueAmount, and others... So, I just changed them to MAX() respectively. Since the group by all those other criteria including the low level ID columns would imply you don't get duplicates, so applying a MAX() to such should be the same value