Access SQL SELECT * WHERE Weeknum<CurrentWeek AND Year<=CurrentYear - sql

I am sure i am missing something obvious, but i cant figure this out.
My problem is very simple
i have a table that contains the following information:
Year, Weeknumber, Data
What i want is to SELECT only data where the weeknumber is less that the current week. That is easy. But what i really want is all data that is registered before the current weeknumber AND current year.
Meaning if i have the following data:
Year Week Data
2019 20 123
2019 21 234
2020 20 345
2020 21 456
If the current week is 21 of 2020 then i want the output to be:
year Week Data
2019 20 123
2019 21 234
2020 20 234
I dont want 2020 - 21 because that is the current year/week
My current query is:
SELECT T.Year, T.Week, T.Data
FROM tblData AS T
WHERE Year<=year(Date()) AND Week<Weeknumber(Date())
The problem with this query is that it doesnt show weeks above 21 in 2019 which i want it to do. I know why this sql doesnt work, but cant figure out how to do it correctly.
How do i do this?

Year is a reserved word and should not use reserved words as names for anything. I used Yr as field name.
Consider:
SELECT Yr, Week, Data
FROM Table1
WHERE [Week] Between 1 And IIf([Yr]=Year(Date()), DatePart("ww", Date()) - 1, 53);

As you are from Denmark, the table will most likely reflect years and weeks according to ISO 8601. However, no native function of VBA will return the ISO 8601 year and week of a date, and - for dates around New Year - the year will often differ from the calendar year.
Thus, functions to return the ISO 8601 year and week are needed:
Public Const MaxWeekValue As Integer = 53
Public Const MinWeekValue As Integer = 1
Public Const MaxMonthValue As Integer = 12
Public Const MinMonthValue As Integer = 1
' Returns the ISO 8601 week of a date.
' The related ISO year is returned by ref.
'
' 2016-01-06. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function Week( _
ByVal Date1 As Date, _
Optional ByRef IsoYear As Integer) _
As Integer
Dim Month As Integer
Dim Interval As String
Dim Result As Integer
Interval = "ww"
Month = VBA.Month(Date1)
' Initially, set the ISO year to the calendar year.
IsoYear = VBA.Year(Date1)
Result = DatePart(Interval, Date1, vbMonday, vbFirstFourDays)
If Result = MaxWeekValue Then
If DatePart(Interval, DateAdd(Interval, 1, Date1), vbMonday, vbFirstFourDays) = MinWeekValue Then
' OK. The next week is the first week of the following year.
Else
' This is really the first week of the next ISO year.
' Correct for DatePart bug.
Result = MinWeekValue
End If
End If
' Adjust year where week number belongs to next or previous year.
If Month = MinMonthValue Then
If Result >= MaxWeekValue - 1 Then
' This is an early date of January belonging to the last week of the previous ISO year.
IsoYear = IsoYear - 1
End If
ElseIf Month = MaxMonthValue Then
If Result = MinWeekValue Then
' This is a late date of December belonging to the first week of the next ISO year.
IsoYear = IsoYear + 1
End If
End If
' IsoYear is returned by reference.
Week = Result
End Function
' Returns the ISO 8601 year of a date.
'
' 2016-01-06. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function YearOfWeek( _
ByVal Date1 As Date) _
As Integer
Dim IsoYear As Integer
' Get the ISO 8601 year of Date1.
Week Date1, IsoYear
YearOfWeek = IsoYear
End Function
An example:
? Week(#2024/12/31#)
1
? YearOfWeek(#2024/12/31#)
2025
Now, use these in your query:
SELECT
T.Year,
T.Week,
T.Data
FROM
tblData AS T
WHERE
T.Year * 100 + T.Week < YearOfWeek(Date()) * 100 + Week(Date())
And you can safely keep Year as the field name as long as you prefix it in queries with the table name as you already do or wrap it in brackets: [Year].

After further testing, June7 was very close, but that sql ended up removing the weeks greater than current week in 2019 (Which i didnt want). I might not have been clear enough in my question, but here is the sql WHERE criteria that gave me what i wanted. Which is, i only want the query to remove data from the current week in the current year. everything older than that, i want shown.
WHERE tbl.Week Between 1 And IIf(tbl.Yr=Year(Date()),Datepart("ww",Date())-1,53)
but thanks for your help #June7, since you guided me straight to the answer

Related

Setting Access dates to various weekdays of the month

I have done a lot of research over the internet for something to help me with what I am trying to do, but haven't been able to come up with anything that helps my situation.
I'm new to using MS Access (using 2013 version) and I am working with a database through my SharePoint 2013 site. What I have is a SharePoint site that keeps track of lots of events through multiple lists. Essentially what I am trying to do is create a list template in SharePoint that I can just upload to the site instead of re-creating the list from scratch every month. With this list I have 1800 events per month and am trying to set the "Date" fields to the first, second, third, etc. Monday of the month, I am trying to do this for Tuesday through Friday also, so that way I don't have to manually set 1800 dates.
I figured this would be possible through MS Access rather than through SharePoint itself. At first I thought I would be able to set the default value to what I need each date field to be, but from my understanding this won't work, so I'm trying to figure out if there is a way to accomplish this in SQL. Now keep in mind that I have never used SQL before so I really don't know what I'm doing with it.
So in case that I didn't explain what I'm trying to do well, I'm trying to set date fields in Access to the 3rd Wednesday of the month, the second Thursday of the month, etc.
Any help is appreciated!
Thanks!
It will be some work to translate to pure SQL as the count of a weekday in a month will be either 4 or 5, but here is a generic function using VBA that does exactly this:
' Calculates the date of the occurrence of Weekday in the month of DateInMonth.
'
' If Occurrence is 0 or negative, the first occurrence of Weekday in the month is assumed.
' If Occurrence is 5 or larger, the last occurrence of Weekday in the month is assumed.
'
' If Weekday is invalid or not specified, the weekday of DateInMonth is used.
'
' 2016-06-09. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function DateWeekdayInMonth( _
ByVal DateInMonth As Date, _
Optional ByVal Occurrence As Integer, _
Optional ByVal Weekday As VbDayOfWeek = -1) _
As Date
Const DaysInWeek As Integer = 7
Dim Offset As Integer
Dim Month As Integer
Dim Year As Integer
Dim ResultDate As Date
' Validate Weekday.
Select Case Weekday
Case _
vbMonday, _
vbTuesday, _
vbWednesday, _
vbThursday, _
vbFriday, _
vbSaturday, _
vbSunday
Case Else
' Zero, none or invalid value for VbDayOfWeek.
Weekday = VBA.Weekday(DateInMonth)
End Select
' Validate Occurence.
If Occurrence <= 0 Then
Occurrence = 1
ElseIf Occurrence > 5 Then
Occurrence = 5
End If
' Start date.
Month = VBA.Month(DateInMonth)
Year = VBA.Year(DateInMonth)
ResultDate = DateSerial(Year, Month, 1)
' Find offset of Weekday from first day of month.
Offset = DaysInWeek * (Occurrence - 1) + (Weekday - VBA.Weekday(ResultDate) + DaysInWeek) Mod DaysInWeek
' Calculate result date.
ResultDate = DateAdd("d", Offset, ResultDate)
If Occurrence = 5 Then
' The latest occurrency of Weekday is requested.
' Check if there really is a fifth occurrence of Weekday in this month.
If VBA.Month(ResultDate) <> Month Then
' There are only four occurrencies of Weekday in this month.
' Return the fourth as the latest.
ResultDate = DateAdd("d", -DaysInWeek, ResultDate)
End If
End If
DateWeekdayInMonth = ResultDate
End Function
Take a look at the WEEKDAY function.
For example you can get the next Sunday for any given date with the following:
=[date] - WEEKDAY([date]) + 7

SQL language in MS ACCESS 2016

i need help with some query in MS ACCESS 2016 with SQL language.
I have a table with 20 employers, and the table includes name, last name, gender, date of birth, date of employment and payment.
I need to calculate specific age, I mean, I want to know who is for example 25 years old of my employers, i dont know how to write command in SQL language to calculate that, i would be very grateful if someone can help me.
You cannot calculate 100% correct age directly in SQL in a simple way.
So use an UDF (user defined function) like this:
Public Function AgeSimple( _
ByVal datDateOfBirth As Date) _
As Integer
' Returns the difference in full years from datDateOfBirth to current date.
'
' Calculates correctly for:
' leap years
' dates of 29. February
' date/time values with embedded time values
'
' DateAdd() is used for check for month end of February as it correctly
' returns Feb. 28. when adding a count of years to dates of Feb. 29.
' when the resulting year is a common year.
' After an idea of Markus G. Fischer.
'
' 2007-06-26. Cactus Data ApS, CPH.
Dim datToday As Date
Dim intAge As Integer
Dim intYears As Integer
datToday = Date
' Find difference in calendar years.
intYears = DateDiff("yyyy", datDateOfBirth, datToday)
If intYears > 0 Then
' Decrease by 1 if current date is earlier than birthday of current year
' using DateDiff to ignore a time portion of datDateOfBirth.
intAge = intYears - Abs(DateDiff("d", datToday, DateAdd("yyyy", intYears, datDateOfBirth)) > 0)
End If
AgeSimple = intAge
End Function
Copy and paste the code into an empty module.
Then run a query:
Select *, AgeSimple([DateOfBirth]) As Age
From YourTable
Where AgeSimple([DateOfBirth]) >= 25
Of course, replace table and field names with those of yours.

Query for a specific length of time (Sql Access)

So I know how to query for a specific date range, but not for a specific length of time.
So rather than looking for records where someone was employed from x date to y date, I'm looking for records where they've been employed for 5 years. Kind of funky, but does anyone have any insight on this?
DateDiff just returns the difference in calendar years, so you need a custom function that uses DateAdd like this:
Public Function AgeSimple( _
ByVal datDateOfBirth As Date) _
As Integer
' Returns the difference in full years from datDateOfBirth to current date.
'
' Calculates correctly for:
' leap years
' dates of 29. February
' date/time values with embedded time values
'
' DateAdd() is used for check for month end of February as it correctly
' returns Feb. 28. when adding a count of years to dates of Feb. 29.
' when the resulting year is a common year.
' After an idea of Markus G. Fischer.
'
' 2007-06-26. Cactus Data ApS, CPH.
Dim datToday As Date
Dim intAge As Integer
Dim intYears As Integer
datToday = Date
' Find difference in calendar years.
intYears = DateDiff("yyyy", datDateOfBirth, datToday)
If intYears > 0 Then
' Decrease by 1 if current date is earlier than birthday of current year
' using DateDiff to ignore a time portion of datDateOfBirth.
intAge = intYears - Abs(DateDiff("d", datToday, DateAdd("yyyy", intYears, datDateOfBirth)) > 0)
End If
AgeSimple = intAge
End Function
Then use SQL similar to:
Select *
From PersonTable
Where AgeSimple([EmploymentDate]) = 5
For Mr. Monkey:
Please pay attention to the in-line comments which explain in full. For example:
' Decrease by 1 if current date is earlier than birthday of current year
To serve this purpose, three "awfully convoluted" lines of code are added:
If intYears > 0 Then
intAge = intYears - Abs(DateDiff("d", datToday, DateAdd("yyyy", intYears, datDateOfBirth)) > 0)
End If
To illustrate the necessity of these, please consider these two examples:
EmploymentDate = #2001/5/1#
Employed = DateDiff("yyyy", EmploymentDate, Date) ' -> 15 years
Employed = AgeSimple(EmploymentDate) ' -> 15 years
EmploymentDate = #2002/11/15#
Employed = DateDiff("yyyy", EmploymentDate, Date) ' -> 14 years
Employed = AgeSimple(EmploymentDate) ' -> 13 years
Use the DATEDIFFFunction
WHERE DATEDIFF ( yy, startdate , enddate ) = 5

Day360 in vb.net

I want to use the Days360 function in VB.Net. I need to know the difference in days between two dates assuming 360 days in a year (not 365 days the DateDiff function uses).
For example DateDiff(DateInterval.Day,"16/10/2015", "04/02/2016") = 111 days, but Days360 should return 109 days.
Days360 function in Excel calculates the days between two dates using a fictional calendar that has 30 days in each month. This method is used for some financial purposes.
You can write a function to do the same calculation.
[Edit]
Excel supports two versions of the calculation: one common in the US (this is the default) and the other common in Europe (see the documentation of the DAYS360 function for details).
The code I originally posted implemented the European version. I have updated it to support both versions. Thanks to Nikhil Vartak for pointing this out.
Function Days360(startDate As DateTime, endDate As DateTime, euMethod As Boolean) As Integer
Dim months As Integer = (endDate.Year - startDate.Year) * 12 + endDate.Month - startDate.Month
If euMethod Then
'Use European method (start or end dates after the 30th of the month are changed to 30th)
Return months * 30 + Math.Min(30, endDate.Day) - Math.Min(30, startDate.Day)
Else 'Use US method
'If the start date is the last day of the month, change it to the 30th
Dim startDay As Integer = startDate.Day
startDay = If(startDate.Day >= DateTime.DaysInMonth(startDate.Year, startDate.Month), 30, startDate.Day)
'If end date is last of the month, change it to the 30th
Dim endDay As Integer = endDate.Day
endDay = If(endDate.Day >= DateTime.DaysInMonth(endDate.Year, endDate.Month), 30, endDate.Day)
'If end date is last of the month and start date is before 30th, change end date to 1st of the next month
If endDate.Day >= DateTime.DaysInMonth(endDate.Year, endDate.Month) And startDay < 30 Then
endDay = 1
months += 1
End If
Return months * 30 + endDay - startday
End If
End Function

VBA Set a specific date to be the first week of the year

I want to set a specific date (October 06 , 2014) to be the 1st Week of the year. So when I use the =weeknum() formulaR1C1 it will return the week number.
I'm currently working on a worksheet that gets updated daily so the week number will be updated every week only. In column ("D") indicates the week number. and column ("B") indicates the daily date.
If i use the =weeknum() formula on it returns the value of 41, but it needs to be week number 1.
How about creating your personalized function?
It just consists of counting how many days there are between the date you insert (myDate) and the date which is considered to be the first day of the year (first_day), dividing this number by 7, taking its integer and adding up 1. It will always give you the right one.
Public Function special_weeknum(ByVal myDate As Date) As Integer
Dim first_day As Date: first_day = #10/6/2014#
Dim myWeek As Integer: myWeek = Int((myDate - first_day) / 7) + 1
special_weeknum = myWeek
End Function
Please note that this approach would allow you also to pass the first day as a user input:
Public Function special_weeknum(ByVal myDate As Date, ByVal first_day As Date)
Dim myWeek As Integer: myWeek = Int((myDate - first_day) / 7) + 1
special_weeknum = myWeek
End Function
so that you will always be able to decide which is the day you must consider as first day of the year.