How can i select the most recent purchase by the Clients? - sql

In a database with several tables and relationships between them, I want to select only the most recent payment by the clients last year.
My query goes like this:
SELECT
P.Name,
EV.EventName,
FN.Installments,
FN.PurchaseValue,
FN.DueDate
FROM ClientPrivate PF
JOIN Client P ON P.PesControle = PF.PesControle
JOIN ClientClass CP ON P.PesControle = CP.PesControle
JOIN EVENT EV ON CP.EveControle = EV.EveControle
JOIN Class cc ON cc.CurControle = EV.CurControle
JOIN Finance FN ON FN.PesControle = P.PesControle
It returns the values I need, only I'd like to get only the most recent purchase by each client, instead of all of them.
I edited to help clarify. The 'Controle' columns are the keys.

Whatever you date column is put that in the ORDER BY Clause of the ROW_NUMBER() function and you are good to go.
;WITH CTE AS
(
SELECT
P.PesNome,
EV.EveDescri,
FN.FinTotParc,
FN.FinVlrLiquido,
FN.FinDiaVencto,
ROW_NUMBER() OVER (PARTITION BY P.PesNome ORDER BY [DateColumn] DESC) rn
FROM PessoaFisica PF
JOIN Pessoa P ON P.PesControle = PF.PesControle
JOIN CursoPessoa CP ON P.PesControle = CP.PesControle
JOIN EVENTO EV ON CP.EveControle = EV.EveControle
JOIN Curso cc ON cc.CurControle = EV.CurControle
JOIN Financeiro FN ON FN.PesControle = P.PesControle
)
SELECT *
FROM CTE
WHERE rn = 1

I'm guessing Financeiro.FinDiaVencto is your purchase date, and that Pessoa.PesControle is a unique identifier for a person. If not, you'll need to modify the query. I'm using Google to translate Portuguese, and it's still not clear to me.
SELECT
P.PesNome,
EV.EveDescri,
FN.FinTotParc,
FN.FinVlrLiquido,
FN.FinDiaVencto
FROM PessoaFisica PF
JOIN Pessoa P
ON P.PesControle = PF.PesControle
JOIN CursoPessoa CP
ON P.PesControle = CP.PesControle
JOIN EVENTO EV
ON CP.EveControle = EV.EveControle
JOIN Curso cc
ON cc.CurControle = EV.CurControle
JOIN Financeiro FN
on FN.PesControle = P.PesControle
WHERE EXISTS (
SELECT 1
FROM PessoaFisica PF_s
JOIN Pessoa P_s
ON P_s.PesControle = PF_s.PesControle
JOIN CursoPessoa CP_s
ON P_s.PesControle = CP_s.PesControle
JOIN EVENTO EV_s
ON CP_s.EveControle = EV_s.EveControle
JOIN Curso cc_s
ON cc_s.CurControle = EV_s.CurControle
JOIN Financeiro FN_s
on FN_s.PesControle = P_s.PesControle
WHERE P_s.PesControle = P.PesControle
HAVING MAX(FN_s.FinDiaVencto) = FN.FinDiaVencto
)
That should return the record with the most recent Financeiro.FinDiaVencto for each Pessoa.PesControle. If you need it by course or by event(?) you'll need to modify the WHERE clause to join on those fields, too.
I'm not sure if that join to PessoaFisica is necessary either, but I included it because it could be eliminating records. You can include a GROUP BY in the subquery, but it should be redundant.

Related

Redshift No Viable Alternative at Input

I have been trying to write some SQL queries that joins 5 tables and selects a subset of the columns to create a new table. I am trying to convert the SQL query into an AWS Glue job, but I am running into a No Viable Alternative at Input error.
I am attaching my query below:
CREATE VIEW cust_ref as
select
------^^^ This is where the error appears.
user_acc_id_int as user_acc_id,
user_acc_skey_int as user_acc_skey,
dg_cust_ref_no
from dim_customer dc where crnt_indc = 1,
address_ref as (select id as address_id, zip from dim_address da ),
zip_ref as (select zip_id, zip from dim_zip)
SELECT
transaction_id,
order_id,
dc.user_acc_id as customer_id,
quantity,
redeem_order_id,
pre_tax_amount,
total_amount,
date(created_at) as sales_date,
user_order_skey,
batch_id,
created_by,
created_dttm,
user_order_skey_int,
nvl(dpart.partner_id,-1) as partner_id,
nvl(dprod.prod_id, -1) as prod_id,
nvl(tstat.trn_status_id, -1) as trn_status_id,
nvl(rtstat.trn_status_id, -1) as redeem_order_status_id,
nvl(ttype.trn_type_id, -1) as trn_type_id
from fact_user_order_stg fuos
--customer lookup--
left join cust_ref dsc on fuos.dg_customer_ref_no = dsc.dg_cust_ref_no
left join cust_ref dsc on fuos.src_dg_customer_ref_no = dsc.dg_cust_ref_no
left join cust_ref ddc on fuos.dst_dg_customer_ref_no = ddc.dg_cust_ref_no
--product lookup
left join (select prod_id , prod_sku from cem_product_staging cps where crnt_indc = 1) dprod
on fuos.product_sku = dprod.prod_sku
--partner lookup--
left join dim_partner dpart on upper(substring(order_id,1,3)) = upper(dpart.partner_prefix)
--zip lookup 2 step--
left join address_ref ba on fuos.billing_address_id = ba.address_id
--left join zip_ref bz on ba.zip = bz.zip
left join address_ref sa on fuos.shipping_address_id = sa.address_id
--left join zip_ref sz on sa.zip = sz.zip
--transaction type, status lookups to follow
left join dim_trn_status tstat on upper(fuos.status) = upper(tstat.trn_status)
left join dim_trn_status rtstat on upper(fuos.redeem_order_status) = upper(tstat.trn_status)
left join dim_trn_type ttype on upper(fuos.\"type\") = upper(ttype.trn_type);
Any guidance would be helpful.
I HAVE TRIED ANSWERS FROM RELATED POSTS which included using "" to fix case sensitive syntax, using a view instead of a WITH clause etc but none of them fixed the problem.

First record in SQL statement

I need to link and additional table to filter by the plant in doing so create multiple records for each entry. I am looking to just get the first entry for one.
SELECT
OrderHead.CreditOverride,
OrderHead.OpenOrder, Customer.CreditHold,
OrderHead.OrderNum, Customer.Name,
OrderHead.EntryPerson, OrderHead.OrderDate,
Customer.TermsCode, OrderHead.ShipToCustNum, OrderRel.Plant
FROM
Customer
INNER JOIN
OrderHead ON Customer.Company = OrderHead.Company
AND Customer.CustNum = OrderHead.BTCustNum
INNER JOIN
OrderRel ON OrderHead.OrderNum = OrderRel.OrderNum
WHERE
(OrderHead.CreditOverride = 0)
AND (OrderHead.OpenOrder = 1)
AND (Customer.CreditHold = 1)
AND (OrderRel.Plant = 'mfgsys')
Trying to grab the first unique record from orderhead.
Use window functions. You can do this entirely in the FROM clause:
FROM Customer c INNER JOIN
(SELECT oh.*,
ROW_NUMBER() OVER (PARTITION BY Company, BTCustNum ORDER BY OrderDate ASC) as seqnum
FROM OrderHead oh
) oh
ON c.Company = oh.Company AND
c.CustNum = oh.BTCustNum AND
oh.seqnum = 1 INNER JOIN
OrderRel orr
ON oh.OrderNum = orr.OrderNum
Note that I replaced the table names with simpler table aliases, which you should repeat in the rest of the query.

SQL-Get and replace minimum value of a query's field

I have the following query in Postgresql :
SELECT mq.nombre,sa.nombre,COUNT(DISTINCT(ae.numero_serie)),SUM(im.fin-im.inicio),MIN(pz.fecha_inicio)
FROM item_metraje AS im LEFT JOIN articulo_especificado AS ae ON (im.id_articulo_especificado = ae.id)
LEFT JOIN articulo AS a ON (ae.id_articulo = a.id)
LEFT JOIN serie_articulo AS sa ON (a.id_serie_articulo = sa.id)
LEFT JOIN reporte_perforacion AS rp ON (rp.id = im.id_reporte_perforacion)
LEFT JOIN pozo AS pz ON (pz.id=rp.id_pozo) LEFT JOIN proyecto AS p ON (p.id=pz.id_proyecto)
LEFT JOIN maquina_perforacion AS mq ON (mq.id = pz.id_maquina)
WHERE p.id = 2 GROUP BY mq.nombre,sa.nombre
and the result is :
However I want to put the minimum date for the rows that have the same value of the field 'nombre', for example for the value 'JM04' the three rows must have the date 2015-01-25 because it is the minimum value of the three rows.
Excuse me for my English and thanks for all.
You can use Window functions for this purpose. MIN(pz.fecha_inicio) over (partition by mq.nombre).
Therefore the final query is,
SELECT z.nombre1,z.nombre2,z.count,z.sum ,MIN(z.date) over (partition by z.nombre1) from
(SELECT mq.nombre as nombre1 ,sa.nombre as nombre2,COUNT(DISTINCT(ae.numero_serie)) as count,SUM(im.fin-im.inicio) as sum ,pz.fecha_inicio as date
FROM item_metraje AS im LEFT JOIN articulo_especificado AS ae ON (im.id_articulo_especificado = ae.id)
LEFT JOIN articulo AS a ON (ae.id_articulo = a.id)
LEFT JOIN serie_articulo AS sa ON (a.id_serie_articulo = sa.id)
LEFT JOIN reporte_perforacion AS rp ON (rp.id = im.id_reporte_perforacion)
LEFT JOIN pozo AS pz ON (pz.id=rp.id_pozo) LEFT JOIN proyecto AS p ON (p.id=pz.id_proyecto)
LEFT JOIN maquina_perforacion AS mq ON (mq.id = pz.id_maquina)
WHERE p.id = 2 GROUP BY mq.nombre,sa.nombre)z
You can modify this with the help of order by or having clauses inside window function as you want. I tried this with my own data set. Hope this helps.

what is this code doing can not understand it

I am trying to figure out what a query is doing and I just do not understand why it would join its self to its self on multiple occassions highlighted bit is the piece i am talking about?
its the part that starts with the [SupplyStatusUpdated] = COALESCE( gas supply and gas supply history
USE [CRM];
SELECT gs.GasSupplyID,
[Account ID] = acc.AccountID,
[GMSReference] = cast(gms.SiteRefNum as varchar),
[AccountNumber] = cast(gms.AccountNum as varchar),
[Organisation Name] = prf.[Name] ,
con.DeclaredDate,
[Contract Date] = CAST(con.ContractDate AS DATE),
[Contract Version] = cv.Name,
[Contract Status] = cs.Name,
loa.ContractEndDate [LOA CED],
gs.CurrentSupplierEndDate [PrevSupplierEndDate],
loa.ContractEndDate,
con.StartDate,
[Supply Status] = gss.Name,
[SupplyStatusUpdated] = COALESCE(
(
SELECT TOP 1 MAX(gsh2.CreatedDate)
FROM GasSupply gs2
INNER JOIN GasSupplyHistory gsh2
ON gsh2.GasSupplyFK = gs2.GasSupplyID
WHERE gsh2.EventFK = 2
AND gsh2.Notes LIKE '%Gas Supply Status (%'
AND gsh2.GasSupplyFK = gs.GasSupplyID
GROUP BY gsh2.GasSupplyFK
),
(
SELECT TOP 1 MAX(gsh3.CreatedDate)
FROM GasSupplyHistory gsh3
INNER JOIN (
SELECT gsh4.GasSupplyFK, MAX(gsh4.EventFK) AS [MaxEvent]
FROM GasSupplyHistory gsh4
WHERE gsh4.GasSupplyFK = gs.GasSupplyID
GROUP BY gsh4.GasSupplyFK
HAVING MAX(gsh4.EventFK) = 1
) dt
ON dt.GasSupplyFK = gsh3.GasSupplyFK
)
),
[EAC] = gs.EstimatedAnnualConsumption,
[PreviousSupplier] = r.name,
[Branch] = b.name,
[LeadSource] = ls.name,
gs.UnitPrice,
gs.StandingCharge,
gs.WholesalePrice,
COALESCE(deal.weeknumber,DATEPART(ISOWK, con.[ContractDate])) AS [Week]
FROM acc.Account acc
INNER JOIN [Profile] prf
ON acc.ProfileFK = prf.ProfileID
INNER JOIN [Contract] con
ON acc.AccountID = con.AccountFK
INNER JOIN [loacontract] lo
ON lo.ContractFK = con.ContractID
LEFT join [LeadSource] ls
ON ls.LeadSourceID = con.LeadSourceFK
INNER JOIN [ContractStatus] cs
ON cs.ContractStatusID = con.ContractStatusFK
INNER JOIN [ContractVersion] cv
ON cv.ContractVersionID = con.ContractVersionFK
INNER JOIN GasSupply gs
ON gs.ContractFK = con.ContractID
INNER JOIN GasSupplyStatus gss
ON gss.GasSupplyStatusID = gs.GasSupplyStatusFK
LEFT JOIN Deal deal
ON deal.ContractFK = con.ContractID
OUTER APPLY GetGMSReferenceNumbers(con.ContractID) gms
LEFT JOIN Branch b
ON b.BranchID = deal.BranchFK
LEFT JOIN DealBroker bro
ON bro.DealFK = deal.DealID
AND bro.BrokerTypeFK = 36
LEFT JOIN Person p
ON p.PersonID = bro.EmployeeFK
LEFT JOIN Reseller r
ON r.ResellerID = gs.ResellerFK
LEFT JOIN (
SELECT l.contractfk,
MIN(l.contractenddate)[ContractEndDate]
FROM CRM.[contract].LOAContract l
GROUP BY l.ContractFK
) loa
ON loa.ContractFK = con.ContractID
WHERE acc.AccountID not in (
select AccountFK
from AccountOption
where OptionFK=9
)
AND cast(gms.SiteRefNum as varchar) IS NULL
COALESCE(Something, SomethingElse) says if the first argument is NULL, return the second argument (note that you can have more than 2 args and it'll just keep going down the list).
As such it's running the first sub-query, and if the result is NULL, returning the result of the second query. Why exactly is your business logic, which we can't answer :-)
(MSDN link on Coalesce)
COALESCE returns the first non-null value it finds, so if the GasSupply query returns a result it will use that: if that returns null it will see if the GasSupplyHistory query returns a result, and if so use that. If both queries return null then SupplyStatusUpdated will be null.
It joins to itself to get historical records from the same source as where it gets the current record.
Representation of historical data is is one common reason for using a BigData/NoSQL database instead of a SQL/Relational database.

Sql Outer Join: Extracting values from multible tables

I am extracting data from multiple tables. mt query is as follows:
SELECT p.Record_Num as RecordNum
,p.GCD_ID as GCDID
,p.Project_Desc as ProjectDesc
,p.Proponent_Name as ProponentName
,st.Station_Name as StationName
,p.OpCentre as OpCentre
,s.Sector_Name as SectorName
,p.PLZone as PLZone
,f.Feeder_Desc as FeederDesc
,d.DxTx_Desc as DxTx
,op.Op_Control_Desc as OpControl
,t.Type_Desc as Type
,c.Conn_Desc as ConnectionKV
,ss.Status_Desc as Status
,p.MW as MW
,p.Subject as Subject
,p.Ip_Num as IpNum
,p.H1N_ID as H1NID
,p.NOMS_Slip_Num as NomsSlipNum
,p.NMS_Updated as NmsUpdated
,p.Received_Date as ReceivedDate
,p.Actual_IS_Date as ActualISDate
,p.Scheduled_IS_Date as ScheduledIsDate
,stst.Station_Name as UpStation
,ff.Feeder_Desc as UpFeeder
,p.HV_Circuit as HVCircuit
,p.SIA_Required as SIAReqd
FROM Project_Detail p,
Station st, Sector s, Feeder f, DxTx d, Operational_Control op, Type t,
Connection_Kv c, Status ss, Station stst, Feeder ff
WHERE
p.Station_ID = st.Station_ID and
p.Sector_ID = s.Sector_ID and
p.Feeder = f.Feeder_ID and
p.DxTx_ID = d.DxTx_ID and
p.OpControl_ID = op.Op_Control_ID and
p.Type_ID= t.Type_ID and
p.ConnKV_ID = c.Conn_ID and
p.Status_ID = ss.Status_ID and
p.UP_Station_ID = stst.Station_ID and
p.UP_Feeder_ID = ff.Feeder_ID
The problem with this query is if it doesnot find an associated value in the second table, it doesnot show the row.
for example : every project has feeders. so if a project_detail table has a feederid which doesnot have an association in the feeder table, then it wont show the row. also, there are times when the feeders are not assigned to a project.
i think i have to use outer joins to get the values. but i cannot figure out how to do that.
please help.
SELECT *
FROM Project_Detail p
LEFT JOIN
Station st
ON p.Station_ID = st.Station_ID
LEFT JOIN
Sector s
ON p.Sector_ID = s.Sector_ID
…
You need LEFT OR FULL OUTER JOINS instead of the inner joins you are now using with your where clause.
SELECT p.Record_Num as RecordNum
,p.GCD_ID as GCDID
,p.Project_Desc as ProjectDesc
,p.Proponent_Name as ProponentName
,st.Station_Name as StationName
,p.OpCentre as OpCentre
,s.Sector_Name as SectorName
,p.PLZone as PLZone
,f.Feeder_Desc as FeederDesc
,d.DxTx_Desc as DxTx
,op.Op_Control_Desc as OpControl
,t.Type_Desc as Type
,c.Conn_Desc as ConnectionKV
,ss.Status_Desc as Status
,p.MW as MW
,p.Subject as Subject
,p.Ip_Num as IpNum
,p.H1N_ID as H1NID
,p.NOMS_Slip_Num as NomsSlipNum
,p.NMS_Updated as NmsUpdated
,p.Received_Date as ReceivedDate
,p.Actual_IS_Date as ActualISDate
,p.Scheduled_IS_Date as ScheduledIsDate
,stst.Station_Name as UpStation
,ff.Feeder_Desc as UpFeeder
,p.HV_Circuit as HVCircuit
,p.SIA_Required as SIAReqd
FROM Project_Detail p
LEFT OUTER JOIN Station st ON p.Station_ID = st.Station_ID
LEFT OUTER JOIN Sector s ON p.Sector_ID = s.Sector_ID
LEFT OUTER JOIN Feeder f ON p.Feeder = f.Feeder_ID
LEFT OUTER JOIN DxTx d ON p.DxTx_ID = d.DxTx_ID
LEFT OUTER JOIN Operational_Control op ON p.OpControl_ID = op.Op_Control_ID
LEFT OUTER JOIN Type t ON p.Type_ID= t.Type_ID
LEFT OUTER JOIN Connection_Kv c ON p.ConnKV_ID = c.Conn_ID
LEFT OUTER JOIN Status ss ON p.Status_ID = ss.Status_ID
LEFT OUTER JOIN Station stst ON p.UP_Station_ID = stst.Station_ID
LEFT OUTER JOIN Feeder ff ON p.UP_Feeder_ID = ff.Feeder_ID