How to decipher complex DATEADD function from MS Access - sql

I have inherited a query from an old MS Access DB and cannot for the life of me figure out what was trying to be done in this date parameter function. I normally only use SQL and this seems a bit different. Can any one assist in describing what this logic is doing?
use pdx_sap_user
go
select po_number,
po_issue_date
from vw_po_header
where po_issue_date > getDate() And PO_issue_date < DateAdd("d",-1,DateAdd("m",8,DateAdd("d",-(Day(getDate())-1),getDate())))

You can de-obfuscate it a lot by using DateSerial:
where
po_issue_date > getDate() And
po_issue_date < DateSerial(Year(getDate()), Month(getDate()) + 8, 0)

First: there is no getDate() function in Access. Probably it should be Date() which returns the current date.
Now starting from the inner expression:
Day(Date()) returns the current day as an integer 1-31.
So in DateAdd("d", -(Day(Date())-1), Date()) from the current date are subtracted as many days as needed to return the 1st of the current month.
Then:
DateAdd("m", 8, DateAdd("d", -(Day(Date())-1), Date()))
adds 8 months to the the 1st of the current month returning the 1st of the month of the date after 8 months.
Finally:
DateAdd("d", -1,...)
subtracts 1 day from the date returned by the previous expression, returning the last day of the previous month of that date.
So if you run today 13-Sep-2019 this code, the result will be:
30-Apr-2020
because this is the last day of the previous month after 8 months.

I think the following:
Take the current date
Substract the current day of month -1 to get the first day of current month
Add 8 month to this
Substract 1 day to get the last day of the previous month
So it calculates some deadline in approx 8 months.
But I wonder how a PO issue date can be in the future...

Related

Based on a Variable Start Date + Days Interval, I need to find the next date after the current day

I have an Anchor Date, eg. 01-01-2020, which is a variable. I also have a days interval, eg. 7 days, which is also a variable. I need to get the next date on or after the current date which is a whole number of intervals after the anchor date.
It's 01-16-2020 right now. The date I would expect is 01-22-2020.
The result date will be within a SELECT Statement as a column. The select statement provides the variables.
Consider:
dateadd(
day,
7 - datediff(day, '2020-01-01', cast(getdate() as date)) % 7,
cast(getdate() as date)
)
Where the anchor date is '2020-01-01' and 7 is the interval.
This works by taking the days difference between the current date and the anchor: for today 2020-01-16, result is 15. Then we get the modulo 7 of this value (which is 1), and substract it from 7 (gives 6), which gives us the number of days that we need to add to the current date to get the expected value (2020-01-22).
Demo on DB Fiddle

How to fix a datetime restriction problem in a sql query?

I'm developing a SQL Query, as a restriction, I want that the query returns data from the first day of the last month until now.
For example: If the query is executed today, the query will only return data entered from 01/03/2019 until today.
To do this, i created the following restriction:
...
SF1010.F1_DTDIGIT>=concat(YEAR(GETDATE()),'0',month(GETDATE())-1,'01') AND
...
The problem is in the months 01, 11 and 12:
If the month is "11", the algorithm will return "1901001" and not "191001".
If the month is "01", the algorithm will return "190001" and not "181201".
Thanks for any help.
SF1010.F1_DTDIGT BETWEEN $yourDate AND date_add($yourDate,interval -DAY($yourDate)+1 DAY)
This gets dates between your date and the first day of the month. first day logic works by subtracting the DAY part to get first of month.
This query will do the comparison of your DTDIGIT with the first day of the previous month in the DATE format:
SF1010.F1_DTDIGIT >= STR_TO_DATE(CONCAT(YEAR(DATE_SUB(NOW(), INTERVAL 1 MONTH)),'-',MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH)),'-','1'), '%Y-%m-%d')
Explanation
DATE_SUB(NOW(), INTERVAL 1 MONTH) returns the date exactly one month ago. We use that date to get the previous month
YEAR() and MONTH() functions use the date explained above
STR_TO_DATE() function converts a string representing a date to the
MySQL DATE format, using the mask (in this example, it's
'%Y-%m-%d').
How about this?
SF1010.F1_DTDIGT >= date_add(date_add(curdate(), interval 1 - day(curdate()) day), interval -1 month)
This assumes the date is not in the future. You can add another condition if that is possible.
If you happen to be using SQL Server, you can do this weird form of date arithmetic:
SF1010.F1_DTDIGT >= dateadd(month, datediff(month, 0, getdate()) - 1, 0)

How to write a variable within SQL using Dateadd and DateDiff for finding the last TWO days of the previous month

I am trying to write a variable using the dateadd and datediff that shows the last two days of previous month. One variable will be the second to last day of the previous month, the one I am having trouble with. The other will be the last day of the previous month, the one I was able to get. I am using SQL Server.
I've tried looking for it on Stack and I have only seen the last day of the previous month given and NOT the second to last day. I tried learning the dateadd and datediff, (which I still want to do).
This is what I tried so far:
Declare #CurrentMonth as date = '3/1/2019'
Declare #SecLastDayPrevMonth as date = DATEADD(MONTH, DATEDIFF(MONTH, 0, #currentmonth), -2)
Declare #LastDayPrevMonth as date = DATEADD(MONTH, DATEDIFF(MONTH, 0, #currentmonth), -1)
The results I am getting for the seclastdayPrevMonth is 2/28/2019. Instead I would want 2/27/2019
I am also getting 2/28/2019 for lastdayprevmonth which is what I want.
I am writing variables because the current month will change every month, and instead of having to update the other days I need within my query, I want to use variables so I am only updating the current month and everything else is flowing through.
And explanation as to why my dateadd/datediff is wrong and an explanation for why the correct dateadd/datediff is the way it is, will be very helpful
Why not refer to the last day when calculating the second last day? Also, your usage of DATEADD is very weird. The syntax is DATEADD(interval, increment, datetime)
Declare #recmonth as date = '3/1/2019'
Declare #LastDayPrevMonth as date = EOMONTH(DATEADD(MONTH, -1, #RecMonth))
Declare #SecLastDayPrevMonth as date = DATEADD(DAY, -1, #LastDayPrevMonth)
SELECT #SecLastDayPrevMonth, #LastDayPrevMonth
So we can calculate the last day of the previous month by subtracting one month from a date and then calling EOMONTH, which returns the last day of a given month. Then the second last day is just subtracting one day from that.
Yields:
SecLastDayPrevMonth LastDayPrevMonth
------------------- ----------------
2019-02-27 2019-02-28
As to "why", DATEDIFF() takes 3 arguments: datepart (string representation of a specific date part), startdate, enddate (both of which must be convertible to a date-ish object).
0 is essentially SQL's epoch, which, in this case is 1/1/1900. So the difference in months between 0 and 3/1/2019 is (119*12)+2 (+2 because we exclude March, since we aren't calculating a full month) = 1430 months difference.
Then, we are trying to add 2 months to our value. DATEADD() takes 3 arguments: datepart, number, date. But, in the example, you are adding 1430 months to whatever date -2 gets converted to (in this case, I believe it would be 12/30/1899, or 2 days before epoch). So, 1430 months after 12/30/1899 would be 2/30/2019, but February only has 28 days in 2019, so it returns 2/28/2019. In a Leap Year, it probably would return 2/29/2019.
To get your #LastDayPrevMonth and #SecLastDayPrevMonth with only DATEDIFF() and DATEADD(), you just need to change your calculations a little.
First thing you want to do is find the First Day of your Given Month. That can be done with DATEADD(month,DATEDIFF(month,0,#CurrentDate),0). We're essentially using the same thing we used above to calculate the number of months since epoch, but then we are adding those months back to epoch.
Now that we know the First Day of the Given Month, all we have to do is subtract days to get a day from the prior month.
So,
DECLARE #CurrentDate date = '2019-03-15' ; -- Changed it to something in the middle of the month.
DECLARE #FirstDayOfGivenMonth = DATEADD(month,DATEDIFF(month,0,#CurrentDate),0) ; -- 3/1/2019
DECLARE #LastDayOfPrevMonth date = DATEADD(day,-1,#FirstDayOfThisMonth) ; -- 2/28/2019
DECLARE #SecLastDayOfPrevMonth date = DATEADD(day, -2, #FirstDayOfThisMonth) ; -- 2/27/2019
SELECT #LastDayOfPrevMonth AS LDPM, #SecLastDayOfPrevMonth AS SLDPM ;
DECLARE #FourDaysLeftInPrevMonth date = DATEADD(day, -4, #FirstDayOfThisMonth) ; -- 2/25/2019
SELECT #FourDaysLeftInPrevMonth AS FourDaysLeftPrev ;
Granted, since SQL 2012, this can all be accomplished much easier with the EOM() function to get to the last day of a month. But if you only could use the two original functions from your original question, this would be one way to get to your needed values.

Teradata Change format of Week Number

I'm pretty new to SQL so I hope this isn't a dumb question, tried to google but couldn't find anything.
I'm summing sales of departments per week in SQL and am using TD_SYSFNLIB.WEEKNUMBER_OF_YEAR (trans_dt) to get the week number.
I think everything is working except I'd like to change the format of the weeks to the start date of the week, e.g. week 1 = 1/4/15
Also, i'm not sure how to handle the very first of the year week 0 since I think that should be grouped up with week 52 of last year.
The following date math trick should get you Beginning of Week as an actual date without having to join to the SYS_CALENDAR view or using a function:
SELECT CURRENT_DATE - ((CURRENT_DATE - DATE '0001-01-07) MOD 7) AS BOW;
Starting with TD14 there's NEXT_DAY which returns the following weekday, if you subtract 7 days you get the previous day:
next_day(trans_dt - 7, 'sunday')

Get birthday greater than current date

my user table is as follows:
birhtMonth: int
dayOfBirthday: int
HireDate: Date
REQUIREMENT: i want to get all upcoming birthdays and hire dates (day/month year is excluded here) in next 6 months, putting in consideration that for current month the day should be greater than today, so here's what i did:
#Query("from User u where ( (u.birthMonth in (8,9,10,11,12,1)) or (month(u.hireDate) in (8,9,10,11,12,1)) ) and u.company = :company")
this gets all upcoming birthdays & hire dates in next six months but it gets birthdays & hire dates in this month for days before & after current day, and it should only get results > current day and ignore results < current day in this month.
EXAMPLE:
today's date is 8/3/2013, if there's birthday with birthMonth=8 and dayOfBirth=3 or 2 or 1 it should be ignored only dayOfBirth > 3 in current month is considered, also if there's hirDate like:
2011-08-01
2012-08-02
2012-08-03
they should be ignored too, please advise how to solve this in sql or hql.
Your hireDate is of type Date, so use a date comparison and use between such as:
(hireDate between :toDayParam and :sixMonthLaterParam)
for birthDate, you can compare with lpad(birthMonth, 2, 0) + lpad(birthDate, 2, 0) but you shall care about whether six month later is in next year or current year.
I think your looking for the DATE functions. They can greatly help you out here. Specifically the DATEADD function. Take a look at the code I made here.
SELECT * FROM dbo.product
WHERE dbo.product.stockDate > GETDATE()
AND dbo.product.stockDate < GETDATE() + DATEADD(month, 6, dbo.product.stockDate)
AND dbo.product.expirationDate > GETDATE()
AND dbo.product.expirationDate < GETDATE() + DATEADD(month, 6, dbo.product.expirationDate)
This will guarantee that the stockDate and the expirationDate are greater than the current date and less than the current date + 6 mo. DATEADD works as follows DATEADD(-what you want to increment by-, -how much you want to increment-, -date to add to-).