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
#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