Facing issue in Access Database query - sql

Order Table Schema
My Access Database Query
Select * from
(
SELECT reseller.id, Max(orders.[order date]) as OrderDate
FROM Reseller INNER JOIN orders ON Reseller.ID = orders.ResellerID
group by reseller.id
)K
WHERE (((K.[OrderDate]) Not Between (Date()-1) And (Date()-18)))
To find those reseller that did not order for 18 Days.
But this is giving below records
Am I missing something ?

Try this query instead:
SELECT *
FROM
(
SELECT reseller.id, Max(orders.[order date]) AS OrderDate
FROM
Reseller
INNER JOIN
orders
ON Reseller.ID = orders.ResellerID
GROUP BY reseller.id
) K
WHERE DateDiff("d", K.[OrderDate], Date()) > 18

Try this
Select * from
(
SELECT reseller.id, Max(orders.[order date]) as OrderDate
FROM Reseller INNER JOIN orders ON Reseller.ID = orders.ResellerID
group by reseller.id
)
WHERE (((K.[OrderDate]) Not Between ( DateAdd("d", -1, Date())
And DateAdd("d", -18, Date())
)
I think when you do Date() - 1 it is subtracting 1 time internal until like subpart of second from the date, not what you intended to subtract 1 date
ALSO, did not change, but do you really want to make the top limits today - 1 day, or just today?

Related

Using MAX function in DateADD SQL. Error - Invalid aggregate function in where clause [MAX(date)]

I have a table 'CSALES' having columns such as customerid,transactiondate,quantity,price. I'm trying to find customers who have not been active in 1 month from a list of dates present in the transactiondate column. I've tried the following code but I'm unsure about the approach and the code is giving a compilation error
SELECT C.CUSTOMERID
FROM CSALES C
WHERE C.CUSTOMERID NOT IN
(
SELECT CS.CUSTOMERID FROM CSALES as CS
WHERE CS.TRANSACTIONDATE > DATEADD(month, -1, MAX(CS.TRANSACTIONDATE )
);
I'm getting the following error
SQL compilation error: Invalid aggregate function in where clause [MAX(CS.TRANSACTIONDATE)]
What changes should I make in the code to reflect the requirement? Would MAX(date) be a right approach ?
SELECT CUSTOMERID
FROM
CSSALES
GROUP BY CUSTOMERID
HAVING
MAX(TRANSACTIONDATE) < ADD_MONTHS(CURRENT_DATE(),-1)
Shawnt00 is right the max date in the transaction table is irrelevant if you just want any customer that hasn't been active in 1 calendar month.
In snowflake use CURRENT_DATE() to get the date portion of Today then ADD_MONTHS(date,int) to get months. Other functions work two but these are pretty easy. If you only want customers to remove duplicate CUSTOMERIDS group by the column.
I think I am about to just repeat Matt's code, but...
With a CTE for some test data:
WITH CSALES(CUSTOMERID, TRANSACTIONDATE) as (
SELECT * FROM VALUES
(1, '2022-05-08'::date), -- to recent
(1, '2021-05-08'::date),
(2, '2021-05-08'::date), -- old enough
(2, '2020-05-08'::date)
)
We can use HAVING for a post aggregation filter.
SELECT C.CUSTOMERID, MAX(C.TRANSACTIONDATE) as last_trans
FROM CSALES C
GROUP BY 1
HAVING last_trans < DATEADD(month,-1,current_date());
As Matt noted there are few ways to find the "one month ago today" he used ADD_MONTHS, I have used DATEADD
CUSTOMERID
LAST_TRANS
2
2021-05-08
Now this code works the same as:
SELECT CUSTOMERID
FROM (
SELECT C.CUSTOMERID, MAX(C.TRANSACTIONDATE) as last_trans
FROM CSALES C
GROUP BY 1
)
WHERE last_trans < DATEADD(month,-1,current_date());
which gives:
CUSTOMERID
2
Albeit we now have hidden away the last transaction, if that was what was wanted, and added some extra select layers for no high level value.
And thus if we want to hide the last_tran in the HAVING version, we can because we have already working code, we can just push the MAX into the HAVING (and we have Matt's code)
SELECT C.CUSTOMERID
FROM CSALES C
GROUP BY 1
HAVING MAX(C.TRANSACTIONDATE) < DATEADD(month,-1,current_date());
which gives for the demo code:
CUSTOMERID
2
Date Options:
There are a couple ways to alter date/time, depending how you like to order you logic, I tend to prefer DATEADD:
SELECT
current_date() as cd_a,
CURRENT_DATE as cd_b,
DATEADD(month, -1, cd_a) as one_month_ago_a,
ADD_MONTHS(cd_a, -1) as one_month_ago_b;
gives:
CD_A
CD_B
ONE_MONTH_AGO_A
ONE_MONTH_AGO_B
2022-05-07
2022-05-07
2022-04-07
2022-04-07
SELECT
C.CUSTOMERID
FROM
CSALES C
GROUP BY
C.CUSTOMERID
HAVING
MAX(C.TRANSACTIONDATE)
<
DATEADD(
month,
-1,
(SELECT MAX(TRANSACTIONDATE) FROM CSALES)
)
Or, assuming you have a customer table...
SELECT
*
FROM
CUSTOMER C
WHERE
NOT EXISTS (
SELECT *
FROM CSALES CS
WHERE CS.CUSTOMERID = C.ID
AND CS.TRANSACTIONDATE >= DATEADD(
month,
-1,
(SELECT MAX(TRANSACTIONDATE) FROM CSALES)
)
)
Demo : dbfiddle
there are multiple possibilities, you must check which is faster
SELECT C.CUSTOMERID
FROM CSALES C
WHERE C.CUSTOMERID NOT IN
(
SELECT CS.CUSTOMERID FROM CSALES as CS CROSS JOIN (SELECT MAX(TRANSACTIONDATE) maxdate FROM CSALES) t1
WHERE CS.TRANSACTIONDATE > DATEADD(month, -1, maxdate)
);
GO
| CUSTOMERID |
| ---------: |
| 4 |
SELECT DISTINCT C.CUSTOMERID
FROM CSALES C CROSS JOIN (SELECT MAX(TRANSACTIONDATE) maxdate FROM CSALES) t1
WHERE NOT EXISTS (SELECT 1 FROM CSALES WHERE CUSTOMERID = c.CUSTOMERID AND TRANSACTIONDATE > DATEADD(month, -1, maxdate))
;
GO
| CUSTOMERID |
| ---------: |
| 4 |
db<>fiddle here

Get the details 1 week before the actual date

I have 3 tables as shown below.
1.
Services
--------------------------
ServiceID (PK,int)
SalesID (FK, int)
ItemName (varchar)
FirstServiceDate (datetime)
2.
Sales
------------------
SalesID (PK,int)
CustomerID (FK,int)
SerialNo (varchar)
ModelNo (varchar)
and 3.
Customer
--------------------
CustomerID (PK,int)
CustName (varchar)
I am trying to get the details from service, sales and customer tables 1 week before FirstServiceDate's date. I tried below query. but it is not working as expected.
Select B.SalesID, C.CustomerID, C.CustomerName, B.SerialNo, B.ModelNo,
A.FirstServiceDate from Services A inner join Sales B on
A.SalesID = B.SalesID inner join Customer C on
B.CustomerID = C.CustomerID and
FirstServiceDate = DATEADD(week, 1, GETDATE())
If the FirstServiceDate is 2 March 2019, then 1 week before (i.e., on 23rd Feb - today). I should get notification.
Any help would be much appreciated.
If the FirstServiceDate column is of type DateTime then you need to convert it to Date:
select
B.SalesID, C.CustomerID, C.CustomerName,
B.SerialNo, B.ModelNo, A.FirstServiceDate
from Services A inner join Sales B
on A.SalesID = B.SalesID
inner join Customer C
on B.CustomerID = C.CustomerID
where convert(date, A.FirstServiceDate) = convert(date, dateadd(week, 1, getdate()))
this way the time part of the dates is eliminated and only the date part is compared.
Edit:
If you want the services scheduled for the next week, change the where part like this:
where
convert(date, A.FirstServiceDate)
between
convert(date, getdate())
and
convert(date, dateadd(week, 1, getdate()))

access sql criteria date 3 months ago

I need to filter a table and show only result that are 3 months ago. So if it is August, to show me May.
Here is my query sql code:
SELECT tblAppointment.WorkID, tblAppointment.AppointmentDate, tblCustomer.CustomerID
FROM tblWork INNER JOIN (tblCustomer INNER JOIN tblAppointment ON tblCustomer.CustomerID = tblAppointment.CustomerID) ON tblWork.WorkID = tblAppointment.WorkID
GROUP BY tblAppointment.WorkID, tblAppointment.AppointmentDate, tblCustomer.CustomerID
HAVING (((tblAppointment.WorkID)=3) AND ((tblAppointment.AppointmentDate) Between Format(DateAdd("m",-3,Date()),"m") And Format(DateAdd("m",-4,Date()),"m")))
ORDER BY tblAppointment.AppointmentDate, tblCustomer.CustomerID;
I am getting a error. I am trying to fix HAVING part.
Please help.
Always handle dates as dates, not text:
SELECT
tblAppointment.WorkID,
tblAppointment.AppointmentDate,
tblCustomer.CustomerID
FROM
tblWork
INNER JOIN
(tblCustomer
INNER JOIN tblAppointment
ON tblCustomer.CustomerID = tblAppointment.CustomerID)
ON tblWork.WorkID = tblAppointment.WorkID
WHERE
tblAppointment.AppointmentDate
Between
DateSerial(Year(Date()), Month(Date())-3, 1)
And
DateSerial(Year(Date()), Month(Date())-2, 0)
GROUP BY
tblAppointment.WorkID,
tblAppointment.AppointmentDate,
tblCustomer.CustomerID
HAVING
tblAppointment.WorkID=3
ORDER BY
tblAppointment.AppointmentDate,
tblCustomer.CustomerID;
Based on your error, and the code, it looks like you are trying to compare dates to strings. Regardless of the GroupBy / Having constructs being necessary, change the Date comparison to:
and DatePart("m", Date()) - DatePart("m", tblAppointment.AppointmentDate)) = 3
You may need to modify to cover the case for the beginning / end of year.
AND (
(
Year(Date()) = Year(tblAppointment.AppointmentDate)
AND
DatePart("m", Date()) - DatePart("m", tblAppointment.AppointmentDate) = 3
)
OR
(
Year(Date()) > Year(tblAppointment.AppointmentDate)
AND
DatePart("m", Date()) + 12 - DatePart("m", tblAppointment.AppointmentDate) = 3
)
)

query to generate transactions from previous month

I need to write a query which when executed at the beginning of the current month must generate a report which contains total transactions made in the previous month and I have written the below query:
SELECT
l.state AS Province
,l.taxing_entity AS TaxJurisdiction
,COUNT(DISTINCT t.trans_id) AS TotalTransCount
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
WHERE
l.chain_id = 10
AND c.issuer_id IN (156967)
AND t.extra_5 BETWEEN LAST_DAY(TODAY - 2 units month) + 1 units day AND LAST_DAY(TODAY - 1 units month)
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
GROUP BY l.state, l.taxing_entity, Province
ORDER BY l.state,l.taxing_entity
But this query throws an error "It is not possible to convert between the specified types. ". I tried changing the date range as below:
t.extra_5 >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0) AND t.extra_5 < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
and
t.extra_5 > DateAdd(WEEK, -1, GETDATE()+1) and t.extra_5<=GETDATE()
But nothing has worked out so far. The current format for the column "extra_5" is as below:
Can someone please suggest a way to get the total transactions from previous month.

How to output only one max value from this query in SQL?

Yesterday Thomas helped me a lot by providing exactly the query I wanted. And now I need a variant of it, and hopes someone can help me out.
I want it to output only one row, namely a max value - but it has to build on the algorithm in the following query:
WITH Calendar AS (SELECT CAST(#StartDate AS datetime) AS Date
UNION ALL
SELECT DATEADD(d, 1, Date) AS Expr1
FROM Calendar AS Calendar_1
WHERE (DATEADD(d, 1, Date) < #EndDate))
SELECT C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM Calendar AS C CROSS JOIN
Country AS C2 LEFT OUTER JOIN
Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
WHERE (C2.Country = #Country)
GROUP BY C.Date, C2.Country OPTION (MAXRECURSION 0)
The output from above will be like:
Date Country Allocated testers
06/01/2010 Chile 3
06/02/2010 Chile 4
06/03/2010 Chile 0
06/04/2010 Chile 0
06/05/2010 Chile 19
but what I need right now is
Allocated testers
19
that is - only one column - one row - the max value itself... (for the (via parameters (that already exists)) selected period of dates and country)
use order and limit
ORDER BY 'people needed DESC' LIMIT 1
EDITED
as LIMIT is not exist in sql
use ORDER BY and TOP
select TOP 1 .... ORDER BY 'people needed' DESC
WITH Calendar
AS (
SELECT
CAST(#StartDate AS datetime) AS Date
UNION ALL
SELECT
DATEADD(d, 1, Date) AS Expr1
FROM
Calendar AS Calendar_1
WHERE
( DATEADD(d, 1, Date) < #EndDate )
)
SELECT TOP 1 *
FROM
(
SELECT
C.Date
,C2.Country
,COALESCE(SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM
Calendar AS C
CROSS JOIN Country AS C2
LEFT OUTER JOIN Requests AS R
ON C.Date BETWEEN R.[Start date] AND R.[End date]
AND R.CountryID = C2.CountryID
WHERE
( C2.Country = #Country )
GROUP BY
C.Date
,C2.Country
OPTION
( MAXRECURSION 0 )
) lst
ORDER BY lst.[Allocated testers] DESC
Full example following the discussion in #Salil answer..
WITH Calendar AS (SELECT CAST(#StartDate AS datetime) AS Date
UNION ALL
SELECT DATEADD(d, 1, Date) AS Expr1
FROM Calendar AS Calendar_1
WHERE (DATEADD(d, 1, Date) < #EndDate))
SELECT TOP 1 C.Date, C2.Country, COALESCE (SUM(R.[Amount of people per day needed]), 0) AS [Allocated testers]
FROM Calendar AS C CROSS JOIN
Country AS C2 LEFT OUTER JOIN
Requests AS R ON C.Date BETWEEN R.[Start date] AND R.[End date] AND R.CountryID = C2.CountryID
WHERE (C2.Country = #Country)
GROUP BY C.Date, C2.Country
ORDER BY 3 DESC
OPTION (MAXRECURSION 0)
the ORDER BY 3 means order by the 3rd field in the SELECT statement.. so if you remove the first two fields, change this accordingly..