Calculated overpay amount base on date condition -SQL Server - sql

I have a code in SQL to retrieve member who has pay date after termination date, and now I also need to calculate the total amount paid after the termination date. How can I achieve that?
There are 2 table, member table:
The final out come I want is:
Currently I am able to retrieve other columns but the Sum(Rcvd Amount)
Select Member_ID
, Term_DT
, RCVD.MAX_RCVD_DT
From Membership a
Left Join
(
Select Member_ID
, MAX(RCVD_DT) as MAX_RCVD_DT
from received
group by Member_ID
)
AS RCVD on RCVD.Member_ID = a.Member_ID
WHERE RCVD.MAX_RCVD_DT >= Term_DT

I think this is just a join -- with an inequality condition -- and aggregation:
select m.memberid, sum(r.rcvd_amount)
from membership m join
received r
on m.memberid = r.memberid and
r.recvd_date > m.term_date
group by m.memberid;

You should use below query:
select m.memberid, max(m.Term_DT) Term_DT, MAX(r.RCVD_DT) as MAX_RCVD_DT, sum(r.rcvd_amount)
from membership m join
received r
on m.memberid = r.memberid and
r.recvd_date > m.term_date
group by m.memberid;

Something like this
select m.Member_ID [Member ID], m.Term_DT [Term Date],
sum(r.RCVD_AMOUNT) [Rcvd Amount], max(r.RCVD_DT) [Latest Rcvd Date]
from membership m
join received r on m.Member_ID = r.Member_ID
and r.RCVD_DT >= m.Term_DT
group by m.Member_ID, m.Term_DT;

Related

Invalid subquery, trying to get the customer ID that goes along with the invoice

Here is my SQL, I am trying to get the DISTINCT item ids that have not been invoiced in the past two years that also have a qty on hand greater than 0. I am having an issue getting the last customer id that was invoiced for each distinct item id.
SELECT DISTINCT
im.item_id,
MAX(il.date_created),
(SELECT TOP 1 customer_id
FROM invoice_hdr ih2
WHERE ih.invoice_no = ih2.invoice_no) AS customer_id,
inv_loc.qty_on_hand,
ih.sales_location_id,
MAX(il.commission_cost)
FROM
invoice_hdr ih
INNER JOIN
invoice_line il ON ih.invoice_no = il.invoice_no
INNER JOIN
inv_mast im ON il.inv_mast_uid = im.inv_mast_uid
INNER JOIN
inv_loc ON im.inv_mast_uid = inv_loc.inv_mast_uid
WHERE
inv_loc.qty_on_hand > '0'
GROUP BY
im.item_id, inv_loc.qty_on_hand, ih.sales_location_id
HAVING
(MAX(il.date_created) < DATEADD(year, -2, GETDATE()))
I get this error:
Column 'invoice_hdr.invoice_no' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I understand the error, but no matter what I try I cannot get it to work.
I was able to get the correct data with the following query:
SELECT DISTINCT il.item_id,
ih.customer_id,
il.customer_part_number,
il.date_created,
SUM(inv_loc.qty_on_hand) AS [Qty On Hand],
ih.sales_location_id,
MAX(il.commission_cost) AS [Max Commission Cost]
FROM invoice_hdr ih
JOIN invoice_line il ON ih.invoice_no = il.invoice_no
JOIN inv_loc ON il.inv_mast_uid = inv_loc.inv_mast_uid
WHERE (SELECT TOP 1 il2.date_created FROM invoice_line il2 WHERE il2.item_id = il.item_id ORDER BY il2.date_created DESC) < DATEADD(YEAR, -2, GETDATE())
AND (SELECT TOP 1 il2.invoice_no FROM invoice_line il2 WHERE il2.item_id = il.item_id ORDER BY il2.date_created DESC) = ih.invoice_no
GROUP BY il.item_id,
ih.customer_id,
il.date_created,
ih.sales_location_id,
customer_part_number
HAVING SUM(inv_loc.qty_on_hand) > 0
ORDER BY il.item_id

Pivoting to append the last 6 payments for 24 loans

I am building a query in Microsoft sql server where I want to find the active loans as well as some information on them. I have built out a common table expression that gives me the correct population. Now I need to get the last 6 payments starting from today. I have a another common table expression that gives all the payments and the payment data received but I am not sure how to pivot and append the last 6 payments such that I have something like this:
This is what the query and output looks like for the common table expression where I can get c1,...,c6.
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
which gives this (but much more):
Here is the whole query I am working from:
Declare #monthEnding date = '3/31/2020',
#monthStart date = '3/1/2020';
WITH Active_Loans as (
SELECT
la.Account,
la.LoanStatus,
la.PrinBal,
isnull(b.Amount, 0) [DUPB],
la.PrinBal + isnull(b.Amount, 0) [TotalUPB],
l.NoteOwner,
pt.[Partition],
l.paidoffdate,
la.[First Name],
la.[Last Name],
la.PmtPI,
la.PmtImpound,
la.NextDueDate,
la.MaturityDate,
la.NoteOwner as [Note Owner]
FROM MARS_DW..vw_vw_Loans_ArchiveEOM la
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
AND b.ArchiveDate = la.ArchiveDate
LEFT JOIN MARS..vw_Loans l on l.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
WHERE la.MonthEnding = #monthEnding
AND la.isActive = 1
AND la.PaidOffDate is null
AND la.LoanStatus NOT LIKE 'BK Payment Plan'
AND la.LoanStatus NOT LIKE 'Prelim'
AND la.LoanStatus NOT like 'trailing claims'
AND la.Account NOT IN (
SELECT account
FROM MARS..vw_Loans
WHERE servicexferdate <=
DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, #monthStart) + 1, 0))
AND PaidOffDate BETWEEN #monthStart AND DATEADD(dd, - 1, DATEADD(mm, DATEDIFF(mm, 0, #monthStart) + 1, 0))
)
UNION
(
SELECT l.account
,la.LoanStatus
,la.PrinBal
,isnull(b.Amount, 0) [DUPB]
,la.PrinBal + isnull(b.Amount, 0) [TotalUPB]
,l.NoteOwner
,pt.[Partition]
,l.PaidOffDate
,la.[First Name]
,la.[Last Name]
,la.PmtPI
,la.PmtImpound
,la.NextDueDate
,la.MaturityDate
,la.NoteOwner as [Note Owner]
FROM MARS..vw_Loans l
LEFT JOIN MARS_DW..vw_vw_Loans_ArchiveEOM la on la.Account = l.Account
LEFT JOIN MARS_DW..vw_DUPBByLoan b on b.Account = la.Account
LEFT JOIN Portfolio_Analytics..partition_table pt on pt.Noteowner = l.NoteOwner
AND b.ArchiveDate = la.ArchiveDate
WHERE l.servicexferdate < #monthEnding
AND l.PaidOffDate > #monthEnding
AND la.MonthEnding = #monthEnding
AND la.LoanStatus NOT like 'trailing claims'
AND la.LoanStatus NOT like 'Inactive - REO/FC'
AND pt.[Partition] IS NOT NULL
)
)
,
payments as
(
SELECT Account,Total,CONVERT(datetime,DateRec) [Date Received]
FROM mars.dbo.vw_PaymentHistory PH
WHERE PH.SourceTyp not like '%fundin%' and PH.SourceTyp not like '%draw%'
)
SELECT
rptpop.Account
, rptpop.[First Name]
, rptpop.[Last Name]
, '$' + CONVERT (VARCHAR (12), rptpop.PmtPI+rptpop.PmtImpound, 1) as PITI
,'$' + CONVERT (VARCHAR (12), rptpop.TotalUPB, 1) as [Total UPB]
, CONVERT(VARCHAR(10),rptpop.NextDueDate,101) as [Next Due Date]
, CONVERT(VARCHAR(10),rptpop.MaturityDate,101) as [Maturity Date]
, rptpop.[Note Owner]
FROM Active_Loans as rptpop
LEFT JOIN payments as pmt on pmt.Account = rptpop.Account
WHERE
rptpop.Partition = 'GAEA'
AND rptpop.LoanStatus = 'Current'
AND rptpop.[Last Name] NOT LIKE '%CRE%'
AND pmt.[Date Received] BETWEEN #monthStart AND #monthEnding
EDIT:
Based on the answer below I was able to do this:
payments as
(
SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY CONVERT(datetime,DateRec) DESC) AS [RowNumber], Total, Account
FROM mars.dbo.vw_PaymentHistory
)
,
get_payment1 as
(
SELECT * FROM payments
where RowNumber = 1
)
Which gives me numbers but what I do not understand is whether 1.) This is indeed correct and 2.) Assuming it is correct how do is it getting the most recent date? Perhaps its the order by clause?
I see a couple of way to solve the problem. I can share the approach using pseudo code.
Create Payments CTE , something like SELECT ROW_NUMBER() OVER(Partition By Account ORDER BY ReceivedDate DESC) . Then create 6 CTE's that use the above CTE with Row_Number 1 thru 6. Then simply use those using Left Join in your query, joining on Account#. This will add c1-c6 columns.
A second approach can be to use the same Payments CTE but instead of multiple CTEs, find a way to use UNPIVOT unpivot (Amount for Rows in (1,2,3,4,5,6) ) u;

Pull top percent of IDs from a list based off of another CTE percentage

I have the below CTE to pull in membership then to pull in all claims for those members ( if they had a claim hit within the date parameters) , now from the total membership (=1961) I need to pull in the TOP 3% or 0.03 from the claims CTE. I see 1961*0.03 is rounded to 59, so I need to pull in the top (59) Medicaid IDs from Claims with the highest total of claims utilization .
So for example in the number_to_pull CTE that gives what lines need to pull in ( it gives the 3% of membership ), then in the sum_of_claims CTE I want to ONLY pull in the top 3% Medicaid IDs from Claims CTE.. Since the membership can change depending on the date parms I want the sum_of_claims to have something like the below but I am not sure how to get started
End result is I will have a list top (3%) of Medicaid IDs who have the most hits per claim for the date span called out
I need something like this, but I want it to pull in whatever the number is in the number_to_pull CTE and then to pull That number based off of the sum of claims.
Select Top ( select
round(count(mt.medicaid_no)*0.03) as percentt
from membership mt)
cll.medicaid_no
,count(distinct claim_number) as sum_of_claims
from claims cll
Group by cll.medicaid_no
) select * from sum_of_claims
This is what my codes actually looks like
WITH
DATES AS
(
select TRUNC(TRUNC(SYSDATE,'y')-1,'y') as startdate,
TRUNC(SYSDATE,'y')-1 as enddate
from dual
),
membership as (
select Distinct
mbr.medicaid_no
,mbd.memb_dim_id
,mbd.memb_demographics_full_date
from dw.fact_member_demographics mbd
inner join dates d
on 1=1
inner join dw.DIM_MEMBER mbr
on mbd.memb_dim_id = mbr.memb_dim_id
Where EXTRACT(YEAR FROM mbd.memb_demographics_full_date)= extract(year from d.startdate)
and mbd.company_dim_id in ('575')
and mbd.age > 18
) ---select * from membership
,number_to_pull as (
select
round(count(mt.medicaid_no)*0.03) as percentt
from membership mt
) ---select * from top_number
,Claims as (
select
mbdd.medicaid_no
,mbdd.memb_dim_id
,dc.company_desc
,cl.primary_svc_date
,cl.claim_number
,case when cl.io_flag_dim_id = '1' then 'Inpatient'
when cl.io_flag_dim_id = '2' then 'Outpatient' else 'false' end as In_Op
,cl.admit_type
,proc.procedure_code
,dx1.diagnosis_code as dx1
,dx1.diagnosis_short_desc as dx1desc
,dx2.diagnosis_code as dx2
,dx2.diagnosis_short_desc as dx2desc
,dx3.diagnosis_code as dx3
,dx3.diagnosis_short_desc as dx3desc
,dx4.diagnosis_code as dx4
,dx4.diagnosis_short_desc as dx4desc
,dx5.diagnosis_code as dx5
,dx5.diagnosis_short_desc as dx5desc
,bt.inp_outp_ind
from membership mbdd
left join dw.fact_claim cl
on mbdd.memb_dim_id = cl.memb_dim_id
inner join dates d
on 1=1
inner join dw.DIM_PROCEDURE_CODE proc
on cl.cpt_code_dim_id = proc.procedure_dim_id
inner join dw.DIM_DIAGNOSIS dx1
on cl.diagnosis_1_dim_id = dx1.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx2
on cl.diagnosis_2_dim_id = dx2.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx3
on cl.diagnosis_3_dim_id = dx3.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx4
on cl.diagnosis_4_dim_id = dx4.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx5
on cl.diagnosis_5_dim_id = dx5.diagnosis_dim_id
inner join dw.DIM_BILL_TYPE bt
on cl.bill_type_dim_id = bt.bill_type_dim_id
inner join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
Where cl.primary_svc_date between d.startdate and d.enddate
and cl.company_dim_id in ('575')
and CL.WHOLE_CLAIM_STATUS_DIM_ID IN (1,2)
and cl.io_flag_dim_id in ('1','2')
) ---select * from claims
,sum_of_claims AS (
Select
---- this is where I want to pull in the top 3% based off of membeship and sum of claims per Medicaid
cll.medicaid_no
,count(distinct claim_number) as sum_of_claims
from claims cll
Group by cll.medicaid_no
) select * from sum_of_claims
The end result I want is a list of Medicaid IDs and there total sum of claims, but this list will ONLY be the top 59 lines (3%)
MEDICAID_NO SUM_OF_CLAIMS
111111 $12,439.61
333333 $5,315.57
444444 $2,007.00
555555 $1,823.98
888888 $1,770.00
777777 $1,211.47
9999999 $1,157.61
6666666 $1,068.76
If I read your question, correctly, you want to get the top 3% here? This is the final query:
select * from sum_of_claims;
I think you want to replace this with something like the following:
SELECT medicaid_no, sum_of_claims FROM (
SELECT medicaid_no, sum_of_claims, COUNT(*) OVER () AS total_cnt
, ROW_NUMBER() OVER ( ORDER BY sum_of_claims DESC ) AS rn
FROM sum_of_claims
) WHERE rn <= 0.03 * total_cnt;
This will get the "top" 3% of records (where "top" is defined as those with the greatest claim amounts).
By the way, I find it hard to believe that this is what you want:
,count(distinct claim_number) as sum_of_claims
That wouldn't give a sum at all!
Hope this helps.
Thanks David F. I was able to pull in the top 3% members from claims . Below is my code .
WITH
DATES AS
(
select TRUNC(TRUNC(SYSDATE,'y')-1,'y') as startdate,
TRUNC(SYSDATE,'y')-1 as enddate
from dual
),
membership as (
select Distinct
mbr.medicaid_no
,mbd.memb_dim_id
,mbd.memb_demographics_full_date
from dw.fact_member_demographics mbd
inner join dates d
on 1=1
inner join dw.DIM_MEMBER mbr
on mbd.memb_dim_id = mbr.memb_dim_id
Where EXTRACT(YEAR FROM mbd.memb_demographics_full_date)= extract(year from d.startdate)
and mbd.company_dim_id in ('575')
and mbd.age > 18
) ---select * from membership
,Claims as (
select
mbdd.medicaid_no
,mbdd.memb_dim_id
,dc.company_desc
,cl.primary_svc_date
,cl.claim_number
,case when cl.io_flag_dim_id = '1' then 'Inpatient'
when cl.io_flag_dim_id = '2' then 'Outpatient' else 'false' end as In_Op
,cl.admit_type
,proc.procedure_code
,dx1.diagnosis_code as dx1
,dx1.diagnosis_short_desc as dx1desc
,dx2.diagnosis_code as dx2
,dx2.diagnosis_short_desc as dx2desc
,dx3.diagnosis_code as dx3
,dx3.diagnosis_short_desc as dx3desc
,dx4.diagnosis_code as dx4
,dx4.diagnosis_short_desc as dx4desc
,dx5.diagnosis_code as dx5
,dx5.diagnosis_short_desc as dx5desc
,bt.inp_outp_ind
,cl.net_amt
from membership mbdd
left join dw.fact_claim cl
on mbdd.memb_dim_id = cl.memb_dim_id
inner join dates d
on 1=1
inner join dw.DIM_PROCEDURE_CODE proc
on cl.cpt_code_dim_id = proc.procedure_dim_id
inner join dw.DIM_DIAGNOSIS dx1
on cl.diagnosis_1_dim_id = dx1.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx2
on cl.diagnosis_2_dim_id = dx2.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx3
on cl.diagnosis_3_dim_id = dx3.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx4
on cl.diagnosis_4_dim_id = dx4.diagnosis_dim_id
inner join dw.DIM_DIAGNOSIS dx5
on cl.diagnosis_5_dim_id = dx5.diagnosis_dim_id
inner join dw.DIM_BILL_TYPE bt
on cl.bill_type_dim_id = bt.bill_type_dim_id
inner join dw.DIM_COMPANY dc
on cl.company_dim_id = dc.company_dim_id
Where cl.primary_svc_date between d.startdate and d.enddate
and cl.company_dim_id in ('575')
and CL.WHOLE_CLAIM_STATUS_DIM_ID IN (1,2) -- pulling in only paid claims -- use whole claim
and cl.io_flag_dim_id in ('1','2')
) ---select * from claims
,sum_of_claims AS (
Select
cll.medicaid_no
,sum(distinct cll.net_amt) as sum_of_claims
from claims cll
Group by cll.medicaid_no
)
----- this is the new part added below
SELECT medicaid_no, sum_of_claims FROM (
SELECT sh.medicaid_no, sh.sum_of_claims, COUNT(*) OVER () AS total_cnt
, ROW_NUMBER() OVER ( ORDER BY sh.sum_of_claims DESC ) AS rn
FROM sum_of_claims sh
)
Where (rn)<(SELECT round(count(medicaid_no)*0.03) as percentt
from membership)

SQL Access Sentence

I been trying to use this sentences that i made in SQL Server Management Studio, on access with no luck, after hours googling, i think they use different languages, can someone help me turn these in Access language?
select c.id_client 'Client ID',
c.client_name 'First Name'
c.client_lname 'Last Name'
from client c join bills b
on c.id_client = b.id_client join bill_detail d
on d.bill_num=b.bill_num
where month (b.date)=3
and year(b.date)= year(getdate())
group by c.id_client, c.client_name,c.client_lname
having d.price > (select avg(prirce) from bill_detail)
select s.id_seller 'Seller ID',
s.seller_name 'First Name',
s.seller_lname 'Last Name',
avg(quantity*d.price),
from sellers s join bills b
on v.id_seller=b.id_seller join bill_detail d
on b.bill_num = d.bill_num
group by s.id_seller, s.seller_name, s.seller_lname
having avg (quantity*d.price) < (select avg(quantity*d.price) from
bill_detail)
select date 'Date',
sum(quantity) 'Tickets Sold',
sum(quantity*d.price) 'Total Amount Sold',
avg(quantity*d.price) 'Average Amount Sold',
from bills b join bill_detail d
on b.bill_num = d.bill_num
group by date
Sry, they were in spanish, hence the awfull english. And thanks in advance.
Useful references:
Converting Access Queries to SQL Server
T-SQL Equivalents for Microsoft Access VBA Functions
I think these will work.. (it's been a while)
SELECT
client.id_client [client id]
, client.client_name [first name]
, client.client_lname [last name]
FROM (client
JOIN bills ON client.id_client = bills.id_client)
JOIN bill_detail ON bill_detail.bill_num = bills.bill_num
WHERE MONTH(bills.date) = 3
AND YEAR(bills.date) = YEAR(DATE())
GROUP BY
client.id_client
, client.client_name
, client.client_lname
HAVING d.price > (
SELECT
AVG(prirce)
FROM bill_detail
)
;
For some reason Access likes parentheses in the from clause. No idea why. There should be MONTH() & YEAR() . Don't recall if Access like table aliases, so I removed them and don't use single quotes for column labels (don't do this is SQL Server either).
SELECT
sellers.id_seller [seller id]
, sellers.seller_name [first name]
, sellers.seller_lname [last name]
, AVG(quantity * bill_detail.price)
FROM (sellers
JOIN bills ON v.id_seller = bills.id_seller)
JOIN bill_detail ON bills.bill_num = bill_detail.bill_num
GROUP BY
sellers.id_seller
, sellers.seller_name
, sellers.seller_lname
HAVING AVG(quantity * bill_detail.price) < (
SELECT
AVG(quantity * bill_detail.price)
FROM bill_detail
)
;
Aside from table & column aliases changes these 2 should be ok.
SELECT
datex [date]
, SUM(quantity) [tickets sold]
, SUM(quantity * bill_detail.price) [total amount sold]
, AVG(quantity * bill_detail.price) [average amount sold]
FROM (bills
JOIN bill_detail ON bills.bill_num = bill_detail.bill_num)
GROUP BY
datex
;
having d.price > (select avg(prirce) from bill_detail)
I think you should change it to avg(price) instead of avg(prirce).
(Must be spelling mistake only)

Filter between dates grouping 3 tables in SQL Server

I have this SQL in SQL Server:
SELECT
Itens.Mercadoria, Mercadoria.Nome, Cabecalho.Data,
SUM(ValorUnitario) AS Total,
SUM(Quantidade) AS Quantidade
FROM
Itens
INNER JOIN
Mercadoria ON Itens.Mercadoria = Mercadoria.Codigo
INNER JOIN
Cabecalho ON Cabecalho.Codigo = Itens.Cabecalho
WHERE
Cabecalho.Data >= '2016-01-01'
AND Cabecalho.Data <= '2018-12-31'
GROUP BY
Itens.Mercadoria, Mercadoria.Nome, Cabecalho.Data
ORDER BY
4 DESC
It is returning the following result.
The highlighted values are repeating, I do not want to be repeated, I want to show only once each item and that the Quantidade and Total fields are SUM.
For example:
`Camisa Polo` -> **Quantidade = 23**
`Calça Jeans` -> **Quantidade = 15**
`Camiseta Estampada` -> **Quantidade = 21**
Assuming thate the relation between Sales and SaleItems is based on SalesId
you can use between assign to your_start_date and your_end_date a proper value
select Products.ProductName
, sum(SaleItems.Price)
, sum(SaleItems.Quantity)
from Products
inner join SaleItems on SaleItems.IdProduct = Products.IdProduct
inner join Sales on Sales.IdSale = SaleItems.IdSale
where SaleDate between your_start_date and your_end_date
group by Products.ProductName
In you case remove or aggregated the Cabecalho.Data column eg:
SELECT Itens.Mercadoria
, Mercadoria.Nome
, SUM(ValorUnitario) AS Total
, SUM(Quantidade) AS Quantidade
FROM Itens INNER JOIN Mercadoria ON Itens.Mercadoria = Mercadoria.Codigo
INNER JOIN Cabecalho ON Cabecalho.Codigo = Itens.Cabecalho
WHERE Cabecalho.Data between '2016-01-01' AND '2018-12-31'
GROUP BY Itens.Mercadoria, Mercadoria.Nome
ORDER BY 4 DESC
or
SELECT Itens.Mercadoria
, Mercadoria.Nome
, max(Cabecalho.Data)
, SUM(ValorUnitario) AS Total
, SUM(Quantidade) AS Quantidade
FROM Itens INNER JOIN Mercadoria ON Itens.Mercadoria = Mercadoria.Codigo
INNER JOIN Cabecalho ON Cabecalho.Codigo = Itens.Cabecalho
WHERE Cabecalho.Data between '2016-01-01' AND '2018-12-31'
GROUP BY Itens.Mercadoria, Mercadoria.Nome
ORDER BY 4 DESC