Query to return records between business years not working correctly - sql

I have found myself in problems querying for records beween business years.
In this case, business year always starts on 01/08/YYYY and end on 31/07/YYYY.
For example:
For 2019-2020 business start: 01/08/2019 ends 31/07/2020
For 2020-2021 business start: 01/08/2020 ends 31/07/2021
When I opened the database today, records still show up even though it is a new business year.
Its as though my queries do not work from the beginning of a new Business year. I have:
'To return records for the Current Business year:
SELECT * FROM tblData WHERE (((DateDiff('m',[PaymentDate],DateSerial(Year(Date()),1,1))) Between -6 And 5));
'To return records for Previous Business year:
SELECT * FROM tblData WHERE (((DateDiff('m',[PaymentDate],DateSerial(Year(Date())-1,1,1))) Between -6 And 5));
My question is, how do I correctly query records for the Current business year and Previous business year?

For the previous business year:
select t.*
from tblData t
where year(dateadd('m', -8, PaymentDate)) = year(date()) - 1
The logic is to subtract 8 months from the date and then extract the year.

If the start and end of business year is constant (yyyy/08/01 - yyyy+1/07/31) then try this - for the current year:
SELECT t.*
FROM tblData As t
WHERE t.PaymentDate BETWEEN DateSerial(Year(Date()), 8, 1) AND DateSerial(Year(Date())+1, 7, 31);
for previous year:
SELECT t.*
FROM tblData As t
WHERE t.PaymentDate BETWEEN DateSerial(Year(Date())-1, 8, 1) AND DateSerial(Year(Date()), 7, 31);
If you would like to pass year value to the query, try this:
--pass year to the query to grab data for business year yyyy/08/01 - yyyy+1/07-31
PARAMETERS BusinessYear SHORT;
SELECT t.*
FROM tblData As t
WHERE t.PaymentDate BETWEEN DateSerial(Year(BusinessYear), 8, 1) AND DateSerial(Year(BusinessYear)+1, 7, 31);
For further details, please see: PARAMETERS declaration (Microsoft Access SQL)

Related

Query to select records between two dates based on the year you are in

This query is supposed to display all records between two dates that fall in different years.
i.e All records between the beginning of August of the previous year and the end of July of the current year. I have used the query below last year but when I opened the database yesterday, I see "No records"
This is clearly wrong as I know there is record in the database. I can see there is a problem in the WHERE ((Year(DateAdd('m',-7,[CommissionDate]))=Year(Date()))) as the new year kicks in. I intend to return all records from the beginning of august of previous year to end of July of current year!
Can I amend the query for it to work correctly?
SELECT IIf(Month([CommissionDate]) In (8,9,10),"Q1",IIf(Month([CommissionDate]) In
(11,12,1),"Q2",IIf(Month([CommissionDate]) In (2,3,4),"Q3","Q4"))) AS Quarter, *
FROM tblAllRecords
WHERE ((Year(DateAdd('m',-7,[CommissionDate]))=Year(Date())))
ORDER BY tblAllRecords.CommissionDate DESC;
This should work:
SELECT
Format(DateAdd("m", 5, [CommissionDate]), "\Qq") As Quarter,
*
FROM
tblAllRecords
WHERE
[CommissionDate] Between
DateSerial(Year(Date()) - 1, 8, 1) And
DateSerial(Year(Date()), 8, 0)
ORDER BY
tblAllRecords.CommissionDate DESC;

Generate custom start and end of months in SQL Server

I'm facing an issue while working with custom dates in T-SQL, we have a client that works with a different methodology of start and end of his month, instead of the default day 01 to start the month and ending in 31, 30 or 29, it's month start at day 26 and ends at 25 of the next month.
E.g., how usually is:
select sum(sales) as sales
from sales
where salesDate between '2020-09-01' and '2020-09-30'
-- or left(salesDate,7) = '2020-09'
Client custom month:
select sum(sales) as sales
from sales
where salesDate between '2020-08-26' and '2020-09-25' -- for setember
So, for this need, I have to calculate how many sales this client did from january until now, month per month, with this custom way... how can I do that?
Example of the query result I want to perform with this month determination:
This is a pretty awful situation. One method is to construct the first date of the month based on the rules:
select mon, sum(sales) as sales
from sales s cross apply
(values (case when day(salesdate) >= 26
then dateadd(month, 1, datefromparts(year(salesdate), month(salesdate), 1))
else datefromparts(year(salesdate), month(salesdate), 1)
) v(mon)
where v.mon >= '2020-01-01'
group by v.mon;
I would recommend adding the fiscal month column as a persisted computed column in the salesDate table so you can add an index and not have to worry about the computation.
Or, better yet, add a calendar table where you can look up the fiscal month for any (reasonable) date.

Adjusting dates and adding new rows

I am trying to calculate the difference between dates but in order to separate them out correctly by month I am hoping to add new rows instead of have a column for each month. I need the following:
If the month of a start date [ss_strt_dtd] equal the month of the end date [ss_end_dtd] then nothing needs to happen.
However, if the the months differ then I need the start date to remain the same but the end date to be the first date of the new month. Then a new start date in the first of the month and the end date to remain the same.
Example:
January 15, 2018 - January 18, 2018 - Nothing needs to happen
January 28, 2018 - February 2, 2018 would need to be split into two
rows that look like this:
[ss_strt_dtd]01/28/2018 [ss_end_dtd]02/01/2018
[ss_strt_dtd]02/01/2018 [ss_end_dtd]02/02/2018
Any thoughts would be appreciated!
You can use UNION:
select ss_strt_dtd, ss_end_dtd from [S&S_Combined]
where year(ss_strt_dtd) = year(ss_end_dtd) and month(ss_strt_dtd) = month(ss_end_dtd)
union all
select ss_strt_dtd, DateSerial(year(ss_end_dtd), month(ss_end_dtd), 1) from [S&S_Combined]
where year(ss_strt_dtd) <> year(ss_end_dtd) or month(ss_strt_dtd) <> month(ss_end_dtd)
UNION ALL select DateSerial(year(ss_end_dtd), month(ss_end_dtd), 1), ss_end_dtd from [S&S_Combined]
where year(ss_strt_dtd) <> year(ss_end_dtd) or month(ss_strt_dtd) <> month(ss_end_dtd);
You can this with a set of queries that also will work if the timespan covers many months.
First a small query to return 10 numbers:
SELECT DISTINCT Abs([id] Mod 10) AS N
FROM MSysObjects;
Save this as Ten.
Then a query to return a the series of months in your date interval:
PARAMETERS
[DateStart] DateTime,
[DateEnd] DateTime;
SELECT
[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100+[Ten_3].[N]*1000+[Ten_4].[N]*10000+[Ten_5].[N]*100000+[Ten_6].[N]*1000000 AS Id,
[DateStart] AS DateStart,
[DateEnd] AS DateEnd,
DateAdd("m",[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100+[Ten_3].[N]*1000+[Ten_4].[N]*10000+[Ten_5].[N]*100000+[Ten_6].[N]*1000000,[DateStart]) AS DateMonth
FROM
Ten AS Ten_0,
Ten AS Ten_1,
Ten AS Ten_2,
Ten AS Ten_3,
Ten AS Ten_4,
Ten AS Ten_5,
Ten AS Ten_6
WHERE
(((DateAdd("m",
[Ten_0].[N]+[Ten_1].[N]*10+[Ten_2].[N]*100+[Ten_3].[N]*1000+[Ten_4].[N]*10000+[Ten_5].[N]*100000+[Ten_6].[N]*1000000,
[DateStart]))<=DateAdd("m",
DateDiff("m", [DateStart],DateAdd("d",-1,[DateEnd])),[DateStart]))
AND ((Ten_0.N)<=DateDiff("m",[DateStart],[DateEnd])\1)
AND ((Ten_1.N)<=DateDiff("m",[DateStart],[DateEnd])\10)
AND ((Ten_2.N)<=DateDiff("m",[DateStart],[DateEnd])\100)
AND ((Ten_3.N)<=DateDiff("m",[DateStart],[DateEnd])\1000)
AND ((Ten_4.N)<=DateDiff("m",[DateStart],[DateEnd])\10000)
AND ((Ten_5.N)<=DateDiff("m",[DateStart],[DateEnd])\100000)
AND ((Ten_6.N)<=DateDiff("m",[DateStart],[DateEnd])\1000000));
Save this as MonthsDateRange.
Finally, calculate the From and To dates for each month respecting the start and end date:
SELECT
MonthsDateRange.Id,
MonthsDateRange.DateStart,
MonthsDateRange.DateEnd,
Year([DateMonth]) AS [Year],
Month([DateMonth]) AS [Month],
IIf(DateDiff("m",[DateStart],[DateMonth])=0,
[DateStart],
DateSerial(Year([DateMonth]),Month([DateMonth]),1)) AS DateFrom,
IIf(DateDiff("m",[DateEnd],[DateMonth])=0,
[DateEnd],
DateSerial(Year([DateMonth]),Month([DateMonth])+1,1)) AS DateTo,
DateDiff("d",[DateFrom],[DateTo]) AS Days
FROM
MonthsDateRange;
Save this as DaysMonthsDateRange.
It will return something like this:
Note, that the query is designed to be able to return the months of the entire range of data type Date.
That is 118800 records from 100-01-01 to 9999-12-31.

how to list the next three month in MS Access Report?

Hey i have an Emp table which have
name + visa no + visa exp date
how i can show in the report the current month and the next 3 month
for example
now iam in march
i need to list the Emp there visa will exp in march + the next 2 month
which is April and may
trying to play with the expression builder but i didn't find a solution or its not possible to done that ??
I am sure your report will have a Query on which it is based, so you need to create a filter in the Query. For example if your Report has a Record Source the name of the Query, then go to the Query design view.
The SQL should be something like,
SELECT
EmployeeName,
EmployeeVisaNo,
EmployeeVisaExpiry
FROM
EmployeeTable
WHERE
Month(EmployeeVisaExpiry) = Month(Date);
To get the information for the current month and the next two months, your Query will be.
SELECT
EmployeeName,
EmployeeVisaNo,
EmployeeVisaExpiry
FROM
EmployeeTable
WHERE
EmployeeVisaExpiry BETWEEN Date() AND DateAdd("m", 3, Date());
I have created the Query to start only form the Date and 90 Days/3 Months from the date, so do not be surprised if it pulls through some entries in June too. However if you want just the three months, then you can have it as,
SELECT
EmployeeName,
EmployeeVisaNo,
EmployeeVisaExpiry
FROM
EmployeeTable
WHERE
Month(EmployeeVisaExpiry) BETWEEN Month(Date) AND Month(DateAdd("m", 3, Date())) ;
The above will give you all the data falling in the three month period, if you want it to filter the ones in the current year, just add an AND to the criteria. Something like,
SELECT
EmployeeName,
EmployeeVisaNo,
EmployeeVisaExpiry
FROM
EmployeeTable
WHERE
((Month(EmployeeVisaExpiry) BETWEEN Month(Date) AND Month(DateAdd("m", 3, Date())))
AND
(Year(EmployeeVisaExpiry) = Year(Date()))) ;

SQL server - Select all items with a date on the previous month

I have a table in my SQL Server database called "items" which has a column called "dateFinished".
I have a script that will run on the 1st day of each month which needs to select all items that finished in the previous month.
So, for example, on the 1st February it will need to select all items where the dateFinished is greater than or equal to 00:00 on the 1st of January and less than 00:00 on 1st February.
it also needs to work across new years (e.g. DEC - JAN).
Any ideas?
Select *
from items
where datefinished >= dateadd(m, datediff(m, 0, GETDATE()) - 1, 0)
AND datefinished < dateadd(m, datediff(m, 0, GETDATE()), 0)
You could get a day of the previous month with dateadd(m,-1,getdate()). Then, filter on the year and month of that date in a where clause, like:
select *
from items
where datepart(yy,dateFinished) = datepart(yy,dateadd(m,-1,getdate()))
and datepart(m,dateFinished) = datepart(m,dateadd(m,-1,getdate()))
This should work across years, and also if the query is run on a later day than the first of the month.
Simple just use what I just used: DATEDIFF(mm,dateFinished,GETDATE()) = 1
SELECT *
FROM items
WHERE DATEDIFF(mm,dateFinished,GETDATE()) = 1
I would start by checking out the DATEADD function
http://msdn.microsoft.com/en-us/library/ms186819.aspx