MS Access date range functions slowing down query - function

I have a query in which I am using a between statement to pull data for a date range. I have a VBA function built, that will evaluate the last date (Max Date) in a table (to get the 1st date for the between) and another function to evaluate the stop date (last date of the between)...So my between date statement looks like this: Between hhMaxDte() And hhLastDte()
For some reason having these 2 functions in my between statement takes what seems to be 8x longer to run the query than if I just manually put the actual dates in myself. Anyone out there know why this is and how I can dynamically do a similar process, but take the same amount of time to run the query, as when I manually enter the dates? My functions code is below:
Function hhMaxDte()
If DMax("row_date", "HH_CIB_Raw_Data") + 1 = Date Then
hhMaxDte = 0
Else
hhMaxDte = DMax("row_date", "HH_CIB_Raw_Data") + 1
End If
End Function
Function hhLastDte()
If DMax("row_date", "HH_CIB_Raw_Data") + 1 = Date Then
hhLastDte = 0
Else
hhLastDte = Date - 1
End If
End Function

I've figured out the answer based off of the feedback in the comments above. The function was running for each row of data, thus significantly slowing down the return of the results. In order to avoid this, I used the built in function Dmax (to analyze the max indexed date in a table) and Date to create a between statement in the Access query criteria section:
Between DMax("row_date","HH_CIB_Raw_Data")+0 And Date()-1
Now the append query is able to dynamically pull data based off of the recent dates missing in the table and runs in a matter of seconds VS 2-3 min.
Thanks for all the input guys!!

Related

MS Access - Use result from query to calculate field value

I'm trying to pull some data from a query in my database into a calculated field in a table. I have dates entered for some jobs I'm recording (DateCallOpened, DateQuoteSent, DateQuoteReceived), as well as WorkType for each job to track the type of work done. I've used calculated fields to find the time it took for each record between those dates. I've also used qryTimings to find the average length of time for the WorkType.
I'd like to build fields that showed the ProjectedQuoteSent, and use the data from my query to calculate the date I can expect the quote to be sent, but I just can't figure out how to pull that data out of the query. I was hoping it would be something as simple as:
=[DateCallOpened]+[qryTimings]:[Avg Of TimeToSendQuote]
You can use a DLookup() function to grab your value from your query. So your formula would be something like:
=[DateCallOpened]+DLookup("Avg Of TimeToSendQuote", "qryTimings", _
"[WorkType]=" & [Forms]![frmMyForm]![txtWorkTypeInput])
See this for more info.

Calling a function from query criteria

I have viewed a lot of what others have asked and answered for this through Google, but have an additional question others haven't covered. My situation is that I am calling an Access query from AUTOMATE, a controller program. The process will run monthly against the data of the preceding month.
My intent is to use two functions declared in a module within Access to put the date range in the WHERE clause, but am finding putting it in on the query criteria line seems to be a problem.
Here are the two functions:
'##################################################################################
' This function returns the date string for the first day of the prior month.
'##################################################################################
Public Function FirstDayPriorMonth() As Date
Dim dateEnd As Date
dateEnd = DateSerial(Year(Date), Month(Date), 0)
FirstDayPriorMonth = dateEnd - Day(dateEnd) + 1
End Function
'##################################################################################
' This function returns the date string for the last day of the prior month.
'##################################################################################
Public Function LastDayPriorMonth() As Date
LastDayPriorMonth = DateSerial(Year(Date), Month(Date), 0)
End Function
The call from AUTOMATE uses DoCmd.OpenQuery to call the query. The SQL version of the full query looks like this:
SELECT dbo_V_HB_Outsourced_AR.REPORTING_DATE,
dbo_V_HB_Outsourced_AR.REPORTING_FISCAL_YEAR AS FY,
dbo_V_HB_Outsourced_AR.LOC_NAME AS FACILITY,
dbo_V_HB_Outsourced_AR.REVCBO_LEGACY_FINANCIAL_CLASS,
dbo_V_HB_Outsourced_AR.EPIC_FINANCIAL_CLASS,
dbo_V_HB_Outsourced_AR.PRIMARY_FIN_CLASS_NAME,
dbo_V_HB_Outsourced_AR.ACCT_STATUS_NAME,
dbo_V_HB_Outsourced_AR.OUTSOURCED_FLAG_YN,
dbo_V_HB_Outsourced_AR.IN_HOUSE_FLAG_YN,
dbo_V_HB_Outsourced_AR.DNFB,
dbo_V_HB_Outsourced_AR.[0-30],
dbo_V_HB_Outsourced_AR.[31-60],
dbo_V_HB_Outsourced_AR.[61-90],
dbo_V_HB_Outsourced_AR.[91-120],
dbo_V_HB_Outsourced_AR.[121-150],
dbo_V_HB_Outsourced_AR.[151-180],
dbo_V_HB_Outsourced_AR.[181-210],
dbo_V_HB_Outsourced_AR.[211-240],
dbo_V_HB_Outsourced_AR.[241-365],
dbo_V_HB_Outsourced_AR.[366+],
dbo_V_HB_Outsourced_AR.[CR BAL],
dbo_V_HB_Outsourced_AR.[Total (Debit Only)],
dbo_V_HB_Outsourced_AR.[Over 90],
dbo_V_HB_Outsourced_AR.COL_AGNCY_NAME
FROM dbo_V_HB_Outsourced_AR
WHERE (((dbo_V_HB_Outsourced_AR.REPORTING_DATE) Between [FirstDayPriorMonth] And [LastDayPriorMonth])
AND ((dbo_V_HB_Outsourced_AR.COL_AGNCY_NAME)='ADVICARE'
Or (dbo_V_HB_Outsourced_AR.COL_AGNCY_NAME)='CONVERGENT'
Or (dbo_V_HB_Outsourced_AR.COL_AGNCY_NAME)='MEDALIST MANAGEMENT')
AND ((dbo_V_HB_Outsourced_AR.LOC_ID)=1010
Or (dbo_V_HB_Outsourced_AR.LOC_ID)=1011
Or (dbo_V_HB_Outsourced_AR.LOC_ID)=1012
Or (dbo_V_HB_Outsourced_AR.LOC_ID)=1013
Or (dbo_V_HB_Outsourced_AR.LOC_ID)=1014));
My question is why can I see the function calls on the query criteria line, but have to change the query in the SQL view? I am still working on getting the function calls to work in the SQL view as well.
I am calling an ACCESS query from AUTOMATE, a controller program.
Unfortunately, a query run from outside an Access application session can not use VBA user-defined functions. That means your FirstDayPriorMonth and LastDayPriorMonth functions are not available in that situation.
Fortunately both those functions are based on fairly simple DateSerial expressions, and DateSerial is usable in any Access query regardless of whether the query is run from within or outside an Access session.
So instead of this ...
Between [FirstDayPriorMonth] And [LastDayPriorMonth]
Use this ...
BETWEEN DateSerial(Year(Date()), Month(Date()) -1, 1)
AND DateSerial(Year(Date()), Month(Date()), 0)
"<first part of query>
from dbo_V_HB_Outsourced_AR
WHERE (((dbo_V_HB_Outsourced_AR.REPORTING_DATE) Between #" & FirstDayPriorMonth() & "# and #" & LastDayPriorMonth() & "#" &
"rest of query"
You need to construct your query string by concatenating the results of the function calls (which should not be in square brackets as they are not field names). Also, dates need a "#" side on each side (in MS-Access).

Odd results in MS Access Query using a DSUM function and parameters

I've just started using MS Access this month and I have a very odd bug. I'm trying to create a query that searches for records in a table that have a maxBenefit (a dsum from a different table's field, with a one to many relationship) within a certain range. I'm using the DSUM function to get the maxBenefit because the table has a dailyBenefits field that need to be added together.
Here is my function:
maxBenefitOfQuote: Nz(DSum("[wholeYearBenefit]","tblDisabilityQuoteDailyBenefits",
"[quoteID] = " & [tblDisabilityQuotes].[ID]))
I know the function works because it produces the correct values. The query also takes in two parameters from a form to create a range for maxBenefits.
I limit the results with this criteria:
>=[Forms]![frmDisabilityFindSimilarQuotes]![minBenefitTotal] And
<=[Forms]![frmDisabilityFindSimilarQuotes]![maxBenefitTotal]
The problem is I get very odd results from the query with maxBenefits outside the range or not returning records with maxBenefits inside the range. If I set the minBenefitTotal to 0 and the max BenefitTotal to 100000000 I get no records returned from the query. If I set the minBenefitTotal to 0 and the maxBenefitTotal to 999999999 I get all the proper records.
Any ideas why this is happening? Thanks in advanced.
First,
Try wrapping both of your inputs in a call to CCur:
>=CCur([Forms]![frmDisabilityFindSimilarQuotes]![minBenefitTotal]) And
<=CCur([Forms]![frmDisabilityFindSimilarQuotes]![maxBenefitTotal])
Next,
If you omit the actual form inputs, and hard-code numbers into the criteria, does it work?
For Example: (>= 0 and <= 100000000)
If that worked... It feels like a string -> number conversion issue. Make sure all string input is actually a number (via CCur()) before sending it into the query.

Getting records from MySQL based on a DateTime column ignoring the time portion using JPA along with Joda-Time

How to filter rows from MySQL database ignoring the time portion of a given DateTime field in MySQL using JPA?
For example, the following segment of code counts the number of rows from a database table that lie between the two dates given in a column of type DateTime in MySQL.
CriteriaBuilder criteriaBuilder=entityManager.getCriteriaBuilder();
CriteriaQuery<Long>criteriaQuery=criteriaBuilder.createQuery(Long.class);
Root<Discount> root = criteriaQuery.from(entityManager.getMetamodel().entity(Discount.class));
criteriaQuery.select(criteriaBuilder.countDistinct(root));
DateTimeFormatter dateTimeFormatter=DateTimeFormat.forPattern("dd-MMM-yyyy hh:mm:ss aa");
DateTime firstDate = dateTimeFormatter.parseDateTime("01-Oct-2013 11:34:26 AM").withZone(DateTimeZone.UTC);
DateTime secondDate = dateTimeFormatter.parseDateTime("31-Oct-2013 09:22:23 PM").withZone(DateTimeZone.UTC);
criteriaQuery.where(criteriaBuilder.between(root.get(Discount_.discountStartDate), firstDate, secondDate));
Long rowCount = entityManager.createQuery(criteriaQuery).getSingleResult();
The two parameters firstDate and secondDate will be in turn dynamic.
How to rewrite this query so that the comparison does not include the time portion in the SQL query which is to be delegated to MySQL.
The column discount_start_date in the entity Discount is designated as follows.
#Column(name = "discount_start_date")
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime discountStartDate;
Seems like you are working too hard.
(a) Apparently, MySQL offers a DATE() function that extracts the date portion of a date-
time field. (I'm a Postgres guy, and don't know MySQL.) You could pursue an approach using that function call as part of your query. But I'm guessing it would faster performance if you first obtained your start and stop time by calculating with Joda-Time in Java before executing the SQL query, as seen below.
(b) Why not do this with a simple SQL query, a two criteria SELECT?
In pseudo-code:
Find Discount records that go into effect from the moment this month starts up until the moment the next month starts.
Use Java and Joda-Time to give you the start & stop values.
org.joda.time.DateTime startOfThisMonth = new org.joda.time.DateTime().dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
org.joda.time.DateTime startofNextMonth = startOfThisMonth.plusMonths( 1 ).dayOfMonth().withMinimumValue().withTimeAtStartOfDay();
Caution: Above code uses default time zone. You should specify a time zone in the constructor.
MySql seems to lack sophisticated time-date handling with time zones etc. So I suppose you would convert those time zoned DateTime objects to UTC.
org.joda.time.DateTime startOfThisMonthInUtc = startOfThisMonth.toDateTime( org.joda.time.DateTimeZone.UTC );
org.joda.time.DateTime startofNextMonthInUtc = startofNextMonth.toDateTime( org.joda.time.DateTimeZone.UTC );
Then do what you do to get date-time values for MySQL.
Then form a query that looks something like this… (Note the use of >= versus < without the Equals sign.)
SELECT title_, amount_, start_date_
FROM discount_
WHERE discount_.start_datetime_ >= startOfThisMonthFromJodaTime
AND discount_.start_datetime_ < startOfNextMonthFromJodaTime
;
When working with date and time, it's generally better to work with the first moment of the day, first moment of the first day of month, etc. rather than try to find the last moment or end time. So my query is based on the idea of find rows whose values go up to, but do not include, the moment after the time frame in which I'm interested.

How to keep a conditional Running Value MS Reporting Services

I am trying to use Reporting Services to create a report displaying the call activity of various sales reps. The report will group by extension and then date of call. For each group of call dates (that is, all the calls for a particular date), I want to display some totals. One of the totals I want to display is the total number of calls whose duration greater than 2 minutes. I can see how to use the RunningValue function to keep a running total of ALL calls for the date, but I'm not sure how to make that conditional on the length of call. Any ideas?
UPDATE: The checked answer below did it... I used a case statement in linq like this:
var qry = from Q in c.CallList
select new
{
Q.Extension,
Q.CallDate,
Q.Duration
CallCountOverTwoMinutes = Q.duration > 120 ? 1 : 0,
};
Then I sum the value of CallCountOverTwoMinutes. Thanks for the help, Chris!
The easiest way would be to pass the value as part of the dataset. For example, using SQL:
SELECT Extension, CallDate, Duration,
CASE WHEN Duration > 2 THEN 1 END AS CallsOver2Mins
FROM CallTable
Then just sum on CallsOver2Mins.