Access DateDiff in an If Statement - database

I am working in Access 2007. I am trying to do something and I think syntax is the issue but everything I'm trying isn't working.
I need a textbox in a report to give me the count of records that have aged more than 30 days, and another that's the same but 60 days. So basically "If the record is more than 30 days past today, count it, or else don't."
The best thing I've done is this:
=Count(IIf(DateDiff("d",[StartDate],Date())>30,""))
[StartDate] is the date the record was put into the database, Date() is today I hope.
It returns a number, but the number is incorrect. I've gotten DateDiff to work outside of an IF statement, so I think it's my syntax, but....what am I doing wrong? Is there a much easier way to do this? I have very limited knowledge of available functions and basically no VBA knowledge.
Thanks so much!!!

Did you try
=Sum(IIf(DateDiff("d",[StartDate],Date())>30, 1, 0))

It looks like you lmisunderstood the iff()
for instance iff(expression,action1,action2) means :
if expression=true then
do action1
else
do action2
end if
So what you're doing basically is counting what datediff returns and not counting the records it matches!
Your approach would be correct if you had your count() in the first action of your iff().
I've got a better solution for you anyway...
Create the following function in your report (edit "MY_TABLE" to match your table's name:
Private Function MyCount(Optional intDays As Integer = 30) As Long
MyCount = DCount("*", "MY_TABLE", "DateDiff('d', [StartDate], Date()) > " & intDays)
End Function
Then you just have to populate your textboxes as a follow
To get the last 30 days count:
MyTextbox.value = MyCount
To get the last 60 days count:
MyTextbox.value = MyCount(60)

Related

How can I determine how many hours per employee are overtime hours while using a conditional function like CASE or CHOOSE?

I'm asked to make a view for a bunch of columns coming from a bunch of different tables. You See the OTHours column needs to be created by taking the Workhours data and seeing if it goes over 40 hours. If it does then I take that number and put it into the OTHours column.
Also If there is a holiday in that week that means anything over 32 hours is considered overtime. Here's some sample data How would I do this without using any variables to store the overtime hours since it must be done using a conditional and or some function?
Try to use CASE statement like this:
select
case
when WorkHours>40 or (WorkHours>32 and HolHours) then WorkHours
else 0
end as OTHours

MS SQL: checking if a timestamp is after expire month(int value)

I need to find expired credit cards in a table. The fields expire_year and expire_month are integer values.
I was thinking something like this could work:
select *
from CREDITCARD
where CURRENT_TIMESTAMP > DATEFROMPARTS(EXPIRE_YEAR, EXPIRE_MONTH, 1);
The problem with this is that the definition of expired would be the first day of the next month. Therefore I need to find a way to write EXPIRE_MONTH + 1. But this is also no good, as the month might be December, in which case I'd be looking for month number 13. In such cases, I'd need to bump the EXPIRE_YEAR instead, and set EXPIRE_MONTH to 1.
I´ve tried to google to the solution, but my issue seems a bit too specific. In Java this would be easy enough to solve, but my SQL knowledge is limited to fairly simple queries.
Something like that :
SELECT DATEADD(month, 1, DATEFROMPARTS(EXPIRE_YEAR, EXPIRE_MONTH, 1))FROM MY_TABLE

Issues when comparing dates in IIF in SSRS matrix

Hi I'm new to ssrs and am attempting to make a report which lists the "Utilisation" percentage of people based on the amount of tasks they have completed and the amount of hours they are working that day, these two values are pulled in by a sql query and "Utilisation" is a calculated field within the report.
This is set up in a matrix format with [date] as the column grouping and [name] as the row grouping, the past year of "Utilisation" is calculated but only the past week from the chosen MaxDate parameter is unhidden in the actual preview.
My problem comes from attempting to calculate the average Utilisation of each person for the past week from the MaxDate parameter. I hope to do the past month aswell.
It just seems like all the code I try, at best just produces #Error when the IFF is true.
Here are some of the things I've tried:
=Sum(IIF(DateDiff("d",Fields!Date.Value, Parameters!MaxDate.Value) < 7, Sum(Fields!Utilisation.Value), ""))
=IIF(DateDiff("d",CDate(Fields!Date.Value), CDate(Parameters!MaxDate.Value)) < 7, Sum(Fields!Utilisation.Value), "")
=IIF(DateAdd("d",-7, Parameters!MaxDate.Value) <= Fields!Date.Value, Sum(Fields!Utilisation.Value), "")
There have been alot more I've tried, these just calculate the total but I would use a count to find the average once I get this working.
My best guess at what's happening is that the IIF statement's only looking at the first Date in the matrix and then comparing that date to see if the conditions true, because if I do:
=IIF(Fields!Date.Value >= "2000/09/20", Sum(Fields!Utilisation.Value), "")
It returns the total of ALL of the Utilisation fields because the first date for each row is after "2000/09/20".
Does anyone have any suggestions?
Thank you
UPDATE:
Something like:
=SUM(IIF(IsNothing(Fields!Date.Value), 0, IIF(DateDiff("d", Fields!Date.Value, Parameters!MaxDate.Value) < 7, 1, 0)), "name")
"works", in that it provides a correct count of the amount of days with a non null utilisation in the past week but as soon as you turn that 1 into a field it errors.
I tried making a work around by making the sql decide whether the day is in the past week or month via W and M codes that are added in the statement. I did this incase the problem was with the date field but even when using the code it doesn't seem to really work. Is this some fundamental limitation with SSRS or am I just consistently fucking up.
=SUM(IIF(IsNothing(Fields!Date.Value), 0, IIF(Fields!Code.Value = "W" , (Fields!TaskTime.Value /Fields!AvailableHours.Value), 0)))
=SUM(IIF(IsNothing(Fields!Date.Value), 0, IIF(Fields!Code.Value = "W" , SUM(Fields!Utilisation.Value), 0)))
=Sum(IIF(Fields!Code.Value = "W", SUM(Fields!TaskTime.Value), 0))
UPDATE
Okay so:
=(IIF(IsNothing(Fields!AvailableHours.Value),"" , SUM(SUM(Fields!TaskTime.Value / Fields!AvailableHours.Value)) / (SUM(Fields!AvailableHours.Value)/7)))
will give me a yearly average from the whole 365 day dataset but for some reason
=(IIF(IsNothing(Fields!WeekCode.Value),"" , SUM(SUM(Fields!TaskTime.Value / Fields!AvailableHours.Value)) / (SUM(Fields!AvailableHours.Value)/7)))
where only the ones within the week of the chosen date are marked with a week code, the rest are applied null, wont work???I don't understand whats happening or why there seem to be these weird limits.
Ok so I didn't find an exact solution to this but I did find a workaround. I guess the problem likely came from using sum on calculated fields within ssrs, to work around this in a arguably inefficient way, within the sql I created 2 more columns that were calculated, weekUtilisation and MonthUtilisation, If the row's date was within a week of the date variable the utilisation was calculated there else there was a null and the same for the monthUtilisation but... within a month of the variable. This allowed me to just do sum(WeekUtilisation) and sum(MonthUtilisation) within SSRS which actually worked and then divide by count of the amount of non nulls in a row this gave me the average I wanted. Doing it within the sql is likely a faster solution anyway.
I've found that the #Error code means that your code was correct and able to be compiled but produced an error. This is usually caused by math equations doing things like dividing by zero or trying to calculate with ambiguous data types.
Try casting all of your Fields and Parameters to the data type that is expected by the comparisons.
For example where you do:
IIF(DateDiff("d", Fields!Date.Value, Parameters!MaxDate.Value) < 7, 1, 0)
do
IIF(DateDiff("d", CDATE(Fields!Date.Value), CDATE(Parameters!MaxDate.Value)) < 7, 1, 0)
and where you have
SUM(SUM(Fields!TaskTime.Value / Fields!AvailableHours.Value))
not sure why you would SUM twice but
SUM(CINT(Fields!TaskTime.Value) / CINT(Fields!AvailableHours.Value))
and make sure those values you are dividing by aren't zero.

SSRS: Hour() for 24:00

I was using Hour(Fields!tempo.Value) for get the hour from a field (tempo). The problem came when I got for first time "24:00" and the report shows the '#error'.
The description in 'Hour' function said:
Returns an Integer value from 0 through 23 representing the hour of
the day
So, I changed the expression to
=IIf(Fields!tempo.Value = "24:00", 0, Hour(Fields!tempo.Value))
but yet I get the #error. Then I tried:
=IIf(Fields!tempo.Value = "24:00", 0, 1)
and correctly I get "0" for 24:00 values and "1" for the rest.
I don't understand why Hour() won't work under IIf().
Maybe exist some better workaround for this case and I don't know it.
Thanks in advances
EDIT:
The idea is get all events which started between 2 hours every day (for filter events from the morning, afternoon and night):
=IIf(Hour(Fields!tempo.Value) >= 22 Or Hour(Fields!tempo.Value) <= 6, SHOWTHIS, Nothing)
if you don't need to perform operations with the hour you can work with strings to get the hour, also if your dataset returns a string this is the simplest solution (IMO).
Try using this expression:
=IIF(LEFT(Fields!tempo.Value,2)="24","0",REPLACE(LEFT(Fields!tempo.Value,2),":",""))
If you still want to get the hour using HOUR function you have to validate twice your field, in the IIF and inside the HOUR function:
=IIF(Fields!tempo.Value="24:00",
0,
HOUR(IIF(Fields!tempo.Value="24:00","0:00",Fields!tempo.Value))
)
Let me know if this helps.

Are these two pieces of SQL code the same?

I'm working with a bit of an older code base where conciseness is not found in many places.
One piece of code we are constantly using in the database is to determine if two dates are within the same program year. For instance, Program Year 2011 begins on July 1st, 2011 and ends on July 1st, 2012(or technically the day before)
The usual way I see that this problem is solved is by using this kind of code:
if Month(#EnrollmentDate)>=7 begin
set #StartDate='07/01/'+LTRIM(RTRIM(Year(#EnrollmentDate)))
set #EndDate='07/01/'+LTRIM(RTRIM(Year(#EnrollmentDate)+1))
end else begin
set #StartDate='07/01/'+LTRIM(RTRIM(Year(#EnrollmentDate)-1))
set #EndDate='07/01/'+LTRIM(RTRIM(Year(#EnrollmentDate)))
end
...
where (ENROLLMENTDATE >= #StartDate and ENROLLMENTDATE < #EndDate)
I recently happened to have to solve this problem and the instant thing that popped in my head was something much more concise:
where year(dateadd(mm,-6,ENROLLMENTDATE)) = year(dateadd(mm,-6,#EnrollmentDate))'
Before I go introducing new bugs into a system that "just works", I'd like to ask SO about this. Are these two pieces of code exactly the same? Will they always give the same output(assuming valid dates)?
the problem I see is that, depending on the optimizer, your solution (that looks better) may not use an index defined on ENROLLMENTDATE since you're doing operations on it, while the original solution would. If there are no indexes on that field, then I don't see an issue
An even easier way to handle this situation is to create a calendar table with a column for the program year. Then there is no logic at all, you just query the values and compare them:
if
(select ProgramYear from dbo.Calendar where BaseDate = #StartDate) =
(select ProgramYear from dbo.Calendar where BaseDate = #EndDate)
begin
-- do something
end
There are many posts on this site about creating calendar tables and using them for many different purposes. In my experience, using a table in this way is always clearer and more maintainable than creating formulas in code.
As it happens, December has 31 days, so no matter how many months you need to subtract, you will always be able to align the resulting date range with a whole year, and therefore your expression will always be true whenever the original one was, even in the general case for an enrolment year starting on other dates.
I once used a dialect of SQL with a range of date manipulation functions that made this slightly easier than string twiddling, something like this:
WHERE enrolmentdate >= #YearBeg(:enrolmentdate + 6 MONTHS) - 6 MONTHS
AND enrolmentdate < #YearBeg(:enrolmentdate + 6 MONTHS) + 6 MONTHS

Resources