MSAccess: list last date paid and sum of all payments - sql

There are 2 tables: TestService and TestPayment, related by ServiceID. The contents of these 2 tables are:
In all there are 3 services and 3 Fees. Each service has multiple payments associated with it; Service 1111 has 2 payments, Service 1112 has 3 payments and Service 1113 has 3 payments. Each payment has an associated DatePaid.
I want a query to show:
For each service, the sum of total payments received for that service, AND the date of the last payment made for that service
To do this I created 3 queries:
TestQPaymentByVHC#: This sums all the payments for each ServiceID
TestQLastInsPayment: This retrieves the date of the last payment for each ServiceID
TestQCPA: This should list all ServiceID’s (one record per ServiceID) with the sum of all payments received (From TestQPaymentByVHC#) and the date of the last payment received for each ServiceID (From TestQLastInsPayment)
Here is the problem:
If TestQLastInsPayment is:
SELECT TOP 1 TestPayment.ServiceID, Last(TestPayment.DatePaid) AS LastOfDatePaid, TestPayment.Amount
FROM TestPayment RIGHT JOIN TestService ON TestPayment.ServiceID = TestService.ServiceID
GROUP BY TestPayment.ServiceID, TestPayment.Amount
ORDER BY Last(TestPayment.DatePaid) DESC;
Then TestQCPA lists the date of the last payment for each ServiceID ONLY for ONE of the ServiceID’s:
If I change TestQLastInsPayment to:
SELECT TestPayment.ServiceID, Last(TestPayment.DatePaid) AS LastOfDatePaid, TestPayment.Amount
FROM TestPayment RIGHT JOIN TestService ON TestPayment.ServiceID = TestService.ServiceID
GROUP BY TestPayment.ServiceID, TestPayment.Amount
ORDER BY Last(TestPayment.DatePaid) DESC;
Then TestQCPA lists all dates of payment for each Service ID and each date a payment was received, and it duplicates records for each ServiceID such that each ServiceID is listed multiple times, one record for each date that a payment was received:
I am doing all this in the GUI and posting the SQL code.
How can I get TestQCPA to list ONLY one line per ServiceID, with the sum of all payments received for that ServiceID, but still have the DatePaid show the last date of payment for each ServiceID?

As I understand the request, the below query should provide the requested information. Max is used instead of last due to how access stores dates as seconds since 00:00:00 1/1/1900.
SELECT TestPayment.ServiceID, Max(TestPayment.DatePaid) AS MaxOfDatePaid, Sum(TestPayment.Amount) AS SumOfAmount
FROM TestPayment INNER JOIN TestService ON TestPayment.ServiceID = TestService.ServiceID
GROUP BY TestPayment.ServiceID
ORDER BY Max(TestPayment.DatePaid);

To include all the fields in your question:
SELECT svc.CPT, svc.Units, svc.Fee, svc.[Patient#], sum(pmt.amount) as [Sum of Amount Paid], max(pmt.datepaid) as [Date of Last Receipt], svc.serviceid
FROM testservice AS svc LEFT JOIN testpayment AS pmt ON svc.serviceid = pmt.serviceid
GROUP BY svc.serviceid, svc.CPT, svc.Units, svc.Fee, svc.[Patient#]
The LEFT JOIN is used because I assume that it is possible that TestService will contain a service for which no payments have yet been received and you said you want to see "for each service, the sum of total payments received for that service".

Thanks for all tips. Turns out problem was I was using LAST(DatePaid). Access does not seem to like LAST function with dates. When I changed to MAX(DatePaid) it all worked.

Related

Find dates with intervals

I have a table full of orders where I want to find the email adresses of customers who have placed orders more than three months ago and that also have not ordered more recent than 3 months. For example
Don't include:
| testman#email.com| 2021-01-01|
| testman#email.com| 2021-05-01|
Do include
| testman2#email.com| 2021-01-01|
I'm not sure how to do this, my start is:
select distinct email
from orders
where order date > 2021-03-28
but don't know how to continue, thanks for any help!
So basically you are trying to find e-mails that have not placed an order during the last three months..?
Let's assume we have a table..
Table of Orders- Example
Using the MAX-function we find the most recent order date for each e-mail. Then filter that result with the HAVING clause to find e-mails whose most recent orders are before 28.3.2021
SELECT E-mail, MAX([Order Date])
FROM Orders
GROUP BY E-mail
HAVING MAX([Order Date]) <= '2021-03-28'

SQL inner query trying to use alias in the where clause

I have a join of 2 tables, that represent a list of payments that contracts have done.
Sample Query: (https://www.db-fiddle.com/f/iXGxgDTopsBBgXGUJsXpa/13)
That sample data consist of 5 contracts, some of them are running behind in payments, so I want to get the list of contracts that havent done a payment in the last 7 days, considering the current date to be: 9 of may of 2021.
For the example, contracts 121, 300, 321 and 400 have made a payment in the last 7 days, so any records from them should not appear in the final query. However:
Contract 321 despite of a payment in the last 7 days they had a reversal that was the total of the credits made by them in the last 7 days, this is equivalent to 0 payments, so I want this contract to appear in my final query.
Contract 121, I dont want to appear in the final result becuase despite of the reversal the is a total credits of 20 (100 credit - 80 reversal)
Contract 400 I want to appear in my results because one of the rows has as codename Special Delete.
In the fiddle I was able to create the query that Filters all records with payments in the last 7 days, but I need help adding the extra filtering:
If any contract that appear there if the sum of the credits and debits is 0, then appear it should appear in the final result (as it is like no payments have been send) this will be the case for the contract 321.
If the credits are positive but one of the rows has as codename "SpecialDelete" then display it in the final result (this is the case for the contract 400)
Total Debits against total credits greater than 0
I will be using this query with AWS Athena
I am guessing the part I need to ammend is (WHERE Payments.ContractID NOT IN ....):
SELECT PaymentID,
Payments.ContractID,
PaymentDate,
Credit,
Debit,
Code,
CodeName,
amount,
city
FROM Payments
LEFT JOIN Info ON Info.ContractID = Payments.ContractID
WHERE Payments.ContractID NOT IN (
SELECT Payments.ContractID
FROM Payments
WHERE PaymentDate >= '20210501'
)
ORDER BY PaymentDate DESC
;
you guess is correct, Here is what you need (if I didn't miss anything):
SELECT p.ContractID,PaymentDate,Credit,Debit,Code,CodeName,amount,city
FROM Payments p
LEFT JOIN Info ON Info.ContractID = p.ContractID
WHERE p.ContractID NOT IN (
SELECT p2.ContractID
FROM Payments p2
WHERE p2.PaymentDate >= '20210501'
group by p2.ContractID
having sum(p2.credit - p2.debit) > 0
) or codename = 'Special Delete'
ORDER BY PaymentDate DESC;

Trying to figure out a solution to this question

Eliminating duplicate answers and mismatch in SQL
So the problem states that I need to find the transactions that happened each day and there is a mismatch between my answer on the correct answer and I don't know why!
this is a Short database description "Recycling firm"
The firm owns several buy-back centers for the collection of recyclable materials. Each of them receives funds to be paid to the recyclables suppliers. Data on funds received are recorded in the table
Income_o(point, date, inc)
The primary key is (point, date), where the point holds the identifier of the buy-back center, and the date corresponds to the calendar date the funds were received. The date column doesn’t include the time part, thus, money (inc) arrives no more than once a day for each center. Information on payments to the recyclables suppliers is held in the table
Outcome_o(point, date, out)
In this table, the primary key (point, date) ensures each buy-back center reports about payments (out) no more than once a day, too.
For the case income and expenditure may occur more than once a day, another database schema with tables having a primary key consisting of the single column code is used:
Income(code, point, date, inc)
Outcome(code, point, date, out)
Here, the date column doesn’t include the time part, either.
and The question is :
Under the assumption that receipts of money (inc) and payouts (out) can be registered any number of times a day for each collection point [i.e. the code column is the primary key], display a table with one corresponding row for each operating date of each collection point.
Result set: point, date, total payout per day (out), total money intake per day (inc).
Missing values are considered to be NULL.
SELECT Income.point, Income."date", SUM("out"), SUM(inc)
FROM Income left JOIN
Outcome ON Income.point = Outcome.point AND
Income."date" = Outcome."date"
GROUP BY Income.point, Income."date"
UNION
SELECT Outcome.point, Outcome."date", SUM("out"), SUM(inc)
FROM Outcome left JOIN
Income ON Income.point = Outcome.point AND
Income."date" = Outcome."date"
GROUP BY Outcome.point, Outcome."date";
My guess is that you have a bit of a Cartesian join by not including CODE as part of your join criteria. I think the following query should suit your needs:
WITH calendar AS
(
SELECT TRUNC(SYSDATE)-(LEVEL-1) AS DT
FROM DUAL
CONNECT BY LEVEL < 30
)
SELECT d.pnt AS "POINT",
c.dt AS "DATE",
d.outcome_total,
d.income_total
FROM calendar c
LEFT JOIN (SELECT nvl(inc.pnt, outc.pnt) AS PNT,
nvl(inc.dt, outc.dt) AS DT,
outc.amt AS OUTCOME_TOTAL,
inc.amt AS INCOME_TOTAL
FROM (SELECT i.pnt, i.dt, sum(i.inc) AS AMT
FROM income i
GROUP BY i.pnt, i.dt) inc
FULL JOIN (SELECT o.pnt, o.dt, sum(o.inc) AS AMT
FROM outcome o
GROUP BY o.pnt, o.dt) outc ON inc.pnt = outc.pnt AND inc.dt = outc.dt) d ON c.dt = d.dt;
I added the calendar table to account for the case where there was neither an income nor an outcome on a given day. However, if you don't need that, the query within the LEFT JOIN should be just fine.
N.B.: With the addition of the calendar WITH clause, this query will currently only show results from the last month(-ish). If you need longer, adjust the 30 day window.

SQL Join using floating Where Date

I have a 2 tables, one with activity generated information, the other with new contract information. Ultimately what I'm trying to do is see if within 30 days after the activity date, a new contract was generated. So for example:
The first table is the activities table, the 2nd the contract table. As you'll see for example, account ABC123 does have a new contract within 30 days of the activity date - CT-7135. However, CT-7695, although it exists in the table and is associated with account ABC123, would not satisfaction the "New Contract" requirement b/c it started outside of the 30 window since the activity date.
Account GJ1234 however would be a "no" b/c there is no contract in the table that is within 30 days of the activity date. Likewise CGE435 (because of CT-4389) and GHE568 (because of contracts CT-4389, CT-8080 AND / OR CT-6690 ---- BUT NOT because of CT-6829) both qualify.
I guess my issue is trying to do this dynamic join off of activity date b/c it's different for each line items.
Thoughts?
Thanks.
Try this:
Select Distinct AccountId
From Accounts a
Where Exists
(Select * From contracts
Where AccountId = a.AccountId
And ContractDate >= a.ActivityDate
And DateDiff(day, a.ActivityDate, ContractDate) <= 30)
The following will find all the accounts that have had a new contract within 30 days of the activity:
SELECT * FROM activities AS A WHERE AccountID IN (SELECT DISTINCT(AccountID) from contracts WHERE ContractStartDate >= A.ActivityDate AND ContractStartDate <= DATE_ADD(A.ActivityDate, INTERVAL DAY 30))

To calculate % in hive query

with the below query i can able to get the approved transaction for per client on per day basis.
select
q1.client_id,
q1.receive_day,
count(q1.client_id) as cnt
from
(select * from sale where response=00) q1
group by
q1.client_id, q1.receive_day
I want to get the approval %, i.e. the approval_per, is 100*(count(client_id)/response), while count(client_id) is the number of clients for the approved transaction.
Response is a count of whole response including all the values (approved and not approved) . I can get the response by select count(response) from sale , but how to make it here for calculating % in the same query is the problem am facing now. I tried out some options as it didn't work , reached user group.
so my expected output format is client_id,receive_day,count(client_id),approval_per.
Any of your help are really appreciated
Thanks & Regards,
dti
You could simply add another subquery which calculates that count. Also for the query you have now it seems unnecessary to have that subquery (q1).
I also make the assumption that you want your percentage should be the percentage of transactions each client is responsible for. I.e. number of transactions for given client divided by number of total transactions.
SELECT
s.client_id,
s.receive_day,
count(s.client_id) as cnt,
100 * (count(s.client_id) / q1.total)
FROM
sale s,
(select count(*) total from sale) q1
WHERE
response = 00
GROUP BY
s.client_id, s.receive_day