Find dates with intervals - sql

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'

Related

MSAccess: list last date paid and sum of all payments

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.

I want NAV price as per (Today date minus 1) date

I have two tables. One is NAV where product daily new price is updated. Second is TDK table where item wise stock is available.
Now I want to get a summery report as per buyer name where all product wise total will come and from table one latest price will come.
I have tried below query...
SELECT dbo.TDK.buyer, dbo.NAV.Product_Name, sum(dbo.TDK.TD_UNITS) as Units, sum(dbo.TDK.TD_AMT) as 'Amount',dbo.NAV.NAValue
FROM dbo.TDK INNER JOIN
dbo.NAV
ON dbo.TDK.Products = dbo.NAV.Product_Name
group by dbo.TDK.buyer, dbo.NAV.Product_Name, dbo.NAV.NAValue
Imnportant: Common columns in both tables...
Table one NAV has column as Products
Table two TDK has column as Product_Name
If I have NAValue 4 records for one product then this query shows 4 lines with same total.
What I need??
I want this query to show only one line with latest NAValue price.
I want display one more line with Units*NAValue (latest) as "Latest Market Value".
Please guide.
What field contains the quote date? I am assuming you have a DATIME field, quoteDate, in dbo.NAV table and my other assumption is that you only store the Date part (i.e. mid-night, time = 00:00:00).
SELECT
t.buyer,
n.Product_Name,
sum(t.TD_UNITS) as Units,
sum(t.TD_AMT) as 'Amount',
n.NAValue
FROM dbo.TDK t
INNER JOIN dbo.NAV n
ON t.Products = n.Product_Name
AND n.quoteDate > getdate()-2
group by t.buyer, n.Product_Name, n.NAValue, n.QuoteDate
GetDate() will give you the current date and time. Subtracting 2 would get it before yesterday but after the day before yesterday.
Also, add n.quoteDate in your select and group by. Even though you don't need it, in case that one day you have a day of bad data with double record in NAV table, one with midnight time and another with 6 PM time.
Your code looks like SQL Server. I think you just want APPLY:
SELECT t.buyer, n.Product_Name, t.TD_UNITS as Units, t.TD_AMT as Amount, n.NAValue
FROM dbo.TDK t CROSS APPLY
(SELECT TOP (1) n.*
FROM dbo.NAV n
WHERE t.Products = n.Product_Name
ORDER BY ?? DESC -- however you define "latest"
) n;

Find most recent date of purchase in user day table

I'm trying to put together a query that will fetch the date, purchase amount, and number of transactions of the last time each user made a purchase. I am pulling from a user day table that contains a row for each time a user does anything in the app, purchase or not. Basically all I am trying to get is the most recent date in which the number of transactions field was greater than zero. The below query returns all days of purchase made by a particular user when all I'm looking for is the last purchase so just the 1st row shown in the attached screenshot is what I am trying to get.
screen shot of query and result set
select tuid, max(event_day),
purchases_day_rev as last_dop_rev,
purchases_day_num as last_dop_quantity,
purchases_day_rev/nullif(purchases_day_num,0) as last_dop_spend_pp
from
(select tuid, event_day,purchases_day_rev,purchases_day_num
from
app.user_day
where purchases_day_num > 0
and tuid='122d665e-1d71-4319-bb0d-05c7f37a28b0'
group by 1,2,3,4) a
group by 1,3,4,5
I'm not going to comment on the logic of your query... if all you want is the first row of your result set, you can try:
<your query here> ORDER BY 2 DESC LIMIT 1 ;
Where ORDER BY 2 DESC orders the result set on max(event_day) and LIMIT 1 extracts only the first row.
I don't know all of the ins and outs of your data, but I don't understand why you are grouping within the subquery without any aggregate function (sum, average, min, max, etc). With that said, I would try something like this:
select tuid
,event_day
,purchases_day_rev as last_dop_rev
,purchases_day_num as last_dop_quantity
,purchases_day_rev/nullif(purchases_day_num,0) as last_day_spend_pp
from app.user_day a
inner join
(
select tuid
,max(event_day) as MAX_DAY
from app.user_day
where purchases_day_num > 0
and tuid='122d665e-1d71-4319-bb0d-05c7f37a28b0'
group by 1
) b
on a.tuid = b.tuid
and a.event_day = b.max_day;

MS Access Query to get multiple counts from the same field

I'm querying imported data that has a date/time field that I can't format as date in the table.
Sample:
Ticket Name Date
INC000101 User1 9/5/2016 10:00:34AM
INC000102 User2 9/5/2016 12:02:00PM
INC000103 User1 9/7/2016 3:34:00PM
INC000104 User2 10/1/2016 9:30:23AM
INC000105 User1 10/5/2016 10:20:00AM
INC000106 USer2 10/6/2016 4:56:00PM
I'm trying to get a count of how many tickets each user has per month. Because the Date field comes from the database as a text field, I can't seem to make that format as date/time so I use "left" to filter by month. This is what I've used to get a return on a single User item for the month of October.
SELECT COUNT(*)
FROM 2016YTD
WHERE [Name]='User1' AND left(Date,3) = '10/';
I would like to add counts for User2 through UserX per month so that I can get a count row or column for each the quantity of tickets for each user each month in one report. Everything I've tried won't save the query due to syntax errors in one form or another. I've tried variations of the following query help post as well without success.
SELECT a.distributor_id,
(SELECT COUNT(*) FROM myTable WHERE level='personal' and distributor_id = a.distributor_id) as PersonalCount,
(SELECT COUNT(*) FROM myTable WHERE level='exec' and distributor_id = a.distributor_id) as ExecCount,
(SELECT COUNT(*) FROM myTable WHERE distributor_id = a.distributor_id) as TotalCount
FROM myTable a ;
I'm sure the answer is staring at me, just not sure what at the moment.
Thanks for reading
John
This is only an answer to your first question about how to deal with dates that are stored in text fields.
To get the count for all users for every month you can do:
SELECT [Name], Format([Date],'mmmm') AS Month, COUNT(*) as Count
FROM 2016YTD
GROUP BY [Name], Format([Date],'mmmm')
A text field containing a date that is always in the same format can be treated as a date with Format() so Format([Date],'mmmm') returns the full month name for each date.
you should just need conditional aggregation. I haven't looked at access in a while but probably just something like this:
SELECT
a.distributor_id
,Format([Date],'mmmm') as Month
,SUM(IIF(level='personal',1,0)) as PersonalCount
,SUM(IIF(level='exec',1,0)) as ExecCount
,COUNT(*) as TotalCount
FROM
myTable a
GROUP BY
a.distributor_id
,Format([Date],'mmmm')

select and delete query based on older entries

I have an Excel sheet that is pushing data to an Access database using ADO. It is essentially putting invoices into a database. Sometimes I will revise my invoice and therefore the database will end up with the same invoice twice. I need to make a select and delete query that will find duplicates based on the invoice number, and delete the older version of the invoice (older record), for a simple example:
id invoice# total item datestamp
1 1234 456.29$ shoes 06/06/2016 03:51
2 1234 78.58$ boots 06/06/2016 03:51
3 1234 22.74$ scarf 06/06/2016 03:51
4 1234 539.34$ shoes 06/07/2016 12:44
4 1234 66.24$ pants 06/07/2016 12:44
As you can see row 4 and 5 are my new invoice for this customer. I want every previous order of the same invoice # to be deleted. Please note: they are not actually duplicates, only the invoice number is duplicated. The query needs to see dupliactes based on invoice number and criteria sees dates older than the most recent date.
At that point it is way beyond me. I would appreciate the help.
Consider using a correlated aggregate subquery in WHERE clause:
DELETE *
FROM InvoiceTable
WHERE NOT datestamp IN
(SELECT Max(datestamp)
FROM InvoiceTable sub
WHERE sub.InvoiceNumber = InvoiceTable.InvoiceNumber)
As I said, try being conservative and not deleting. Instead, select rows that are based on the maximum date stamp for a given invoice number:
SELECT
invoices.id, invoices.invoice, invoices.total, invoices.item, invoices.datestamp
FROM
invoices
INNER JOIN
(SELECT
id, MAX(datestamp) AS maxdate
FROM
invoices
GROUP BY
id) lastinv
ON invoices.id = lastinv.id AND
invoices.datestamp = lastinv.maxdate
This is untested code, but should, pretty much do what you want. All you have to do is mangle it into Microsoft Access, as this is T-SQL.