I'm using MS Access 2013 (without any access to other SQL programs).
I have to filter data, based on daily breakdowns across 30 years (10800 rows to start with) for more than 50 customers (540.000 rows in total). I have an issue with the speed of my queries. After a few joins and filters the whole thing takes seconds to run. To speed up the calculation I tried:
breaking queries down (using as few joins as possible)
filtering for 'active data' only;
aggregating iteration queries;
indexed the dates (as Integers).
In need to add, for each calendar date, the summed DealValue, aggregated by Customer, for it's 'active period' (each day between the StartDate and EndDate of the given Deal). The deals may spread over 30 years. Looks like that LEFT JOIN is causing all the slow-down.
My final query looks like:
SELECT QMaster.CalDate,
QDeals.CustomerID,
Sum(IIf([QDeals]![Limit]="S",[QDeals.DealValue],0)) AS S,
Sum(IIf([QDeals]![Limit]="L",[QDeals.DealValue],0)) AS L
FROM QMaster
LEFT JOIN TDeals
ON (QMaster.CalDate> QDeals.DealStartDate)
AND (QMaster.CalDate< QDeals.DealEndDate)
GROUP BY QMaster.CalDate, QDeals.CustomerID;
-- where QMaster (540.000 rows) / QDeals (> 10.000 rows) / calculation time 5<>7s
-- the query may contain typos as I had to change the name description for disclosure.
Any tips on how to replace that LEFT JOIN?
Or any other speed improvements prior to this query?
I want to add an 'interactive' Access form over my 'master' query and that's turning to be very slow (not user friendly).
Related
I have a table (Access 2016) tbl_b with date/time registrations
b_customer (num)
b_date (date)
b_start (date/time)
b_end (date/time)
I want to make a chart of all time registrations per day in a selected month and the gaps between those times. For this I need a query or table showing all times as source for the chart. I’m a bit lost how to approach this.
I assume the chart source needs consecutive records with all date and time registrations to do this. My approach would be create a temporary table (tmp) calculating all time periods where the customer is null. The next step would be a union query to combine the tbl_b and tmp table.
The tbl_b does not have records for every day, so I use a query generating all days in the selected month which shall be used in the chart (found this solution here: [Create a List of Dates in Access Query)
The disadvantage of using a tmp table for the “time gaps” is that it is not updating real time, where a query would provide this opportunity. I have about 20 queries to perform the end result, but MS Access keeps giving (expected) errors that the queries are too difficult.
Every query looks for difference between the in the previous query found end time and the next start time. On the other hand this approach has a weaknes as well, I thought 15 steps would be enough (no more than 15 gaps expected), but this is not sure.
Can anyone give me a head start how this can be accomplished by an easier (and actual working) method? Maybe VBA?
Thx!
Art
I need to report the total time of all queries executed by a certain module in one day.
-- sum over all queries executed the last 24 hours
select
u.username,
sum(round(v.ELAPSED_TIME / 3600000000 * 60,2)) ELAPSED_TIME_MINUTES,
sum(round(v.ELAPSED_TIME / 3600000000,2)) ELAPSED_TIME_HOURS,
v.module
from gv$sql v
left join dba_users u
on v.parsing_user_id = u.user_id
where u.username like '%XYZ' and module = 'WEBSERVER'
and to_date(v.FIRST_LOAD_TIME,'yyyy-mm-dd hh24:mi:ss') > (trunc(sysdate,'DD') - interval '1' day)
group by username,module;
But I am aksing myself the following:
has v$sql all the queries and how long? it is at least empty after flushing the shared pool
is there a better way to calculate to total time consumed by queries in a certain timeframe?
is FIRST_LOAD_TIME the right field to find the correct day. According to Oracle it is a Timestamp of the parent creation time - should be correct?
Thank you for joining a discussion!
Rows in V$SQL for certain statements disappear after they complete, either due to hints, or due to the nature of the sql statement, such as CREATE TABLE goes away.
If you are setting the MODULE via DBMS_APPLICATION_INFO.SET_MODULE(mod_name, action_name); and have SQL tuning licensed, then just user the Automatic Workload Management (AWR) framework; it includes the MODULE information in the reports it can produce, and gives you number of executions, plus lots of other information.
FIRST_LOAD_TIME could be days ago, or a few moments ago.
I would stay away from V$SQL -- it is too dynamic for what you want to do; and use the SET_MODULE to set the module name, and possibly set a different action name for different parts of your code.
I have a Calendar table pulled from our mainframe DBs and saved as a local Access table. The table has history back to the 1930s (and I know we use back to the 50s in at least one place), resulting in 31k records. This Calendar table has 3 fields of interest:
Bus_Dt - every day, not just business days. Primary Key
Bus_Day_Ind - indicates if the day was a valid business day for the stock market.
Prir_Bus_Dt - the prior business day. Contains some errors (about 50), all old.
I have written a query to retrieve the first business day on or after the current calendar day, but it runs supremely slowly. (5+ minutes) I have examined the showplan output and see it is being run via an x-join, which between 30k+ record tables gives a solution space (and date comparisons) in the order of nearly 10 million. However, the actual task is not hard, and could be preformed comfortably by excel in minimal time using a simple sort.
My question is thus, is there any way to fix the poor performance of the query, or is this an inherent failing of SQL? (DB2 run on the mainframe also is slow, though not crushingly so. Throwing cycles at the problem and all that.) Secondarily, if I were to trust prir_bus_dt, can I get there better? Or restrict the date range (aka, "cheat"), or any other tricks I didn't think of yet?
SQL:
SELECT TE2Clndr.BUS_DT AS Cal_Dt
, Min(TE2Clndr_1.BUS_DT) AS Next_Bus_Dt
FROM TE2Clndr
, TE2Clndr AS TE2Clndr_1
WHERE TE2Clndr_1.BUS_DAY_IND="Y" AND
TE2Clndr.BUS_DT<=[te2clndr_1].[bus_dt]
GROUP BY TE2Clndr.BUS_DT;
Showplan:
Inputs to Query
Table 'TE2Clndr'
Table 'TE2Clndr'
End inputs to Query
01) Restrict rows of table TE2Clndr
by scanning
testing expression "TE2Clndr_1.BUS_DAY_IND="Y""
store result in temporary table
02) Inner Join table 'TE2Clndr' to result of '01)'
using X-Prod join
then test expression "TE2Clndr.BUS_DT<=[te2clndr_1].[bus_dt]"
03) Group result of '02)'
Again, the question is, can this be made better (faster), or is this already as good as it gets?
I have a new query that is much faster for the same job, but it depends on the prir_bus_dt field (which has some errors). It also isn't great theory since prior business day is not necessarily available on everyone's calendar. So I don't consider this "the" answer, merely an answer.
New query:
SELECT TE2Clndr.BUS_DT as Cal_Dt
, Max(TE2Clndr_1.BUS_DT) AS Next_Bus_Dt
FROM TE2Clndr
INNER JOIN TE2Clndr AS TE2Clndr_1
ON TE2Clndr.PRIR_BUS_DT = TE2Clndr_1.PRIR_BUS_DT
GROUP BY TE2Clndr.BUS_DT;
What about this approach
select min(bus_dt)
from te2Clndr
where bus_dt >= date()
and bus_day_ind = 'Y'
This is my reference for date() representing the current date
I have a Microsoft Access 2010 database of thyroid surgeries. I have a query that counts the number of surgeries in the entire database. I have a second query that counts the number of surgeries performed between certain dates. I created a new query using SQL to calculate the percentage of surgeries in that date range (a percentage of the total surgery number). Here is the code:
SELECT
((select count(ThyroidSurgeryType)
from [Thyroid Surgeries]
HAVING ([Thyroid Surgeries].SurgeryDate) Between #1/1/2011# And #12/31/2012#)/(select count(ThyroidSurgeryType)
from [Thyroid Surgeries])) AS Percentage
FROM [Thyroid Surgeries];
I get .33 (I then set the row format to percentage to get 33%), but I get 6 rows of 33% as opposed to just one. Why is it displaying this way? Thanks
The way you're using inline queries, you're executing the same query per row of the outer query. So if your table has six rows, you'd be executing it six time (and getting the same result for each query, naturally). You can simplify things by removing the outer query and using an iif expression:
SELECT SUM (IIF (SurgeryDate Between #1/1/2011# And #12/31/2012#, 1, 0)) /
COUNT(ThyroidSurgeryType) AS Percentage
FROM [Thyroid Surgeries];
For security reasons, we're using a front end application, where we're uploading a txt file, deleting 2500 records from a SQL database.
I'm using SQL Server 2008 Mgt Studio to query the progress of that delete. But this just shows me how many rows I have left, not how much time is left.
How can I add into my query?
A calculation of the estimate 'in minutes', remaining on a record deletes?
While there is no fixed amount of time it takes to complete, its been averaging 1.5min to delete each record.
I figured simple math (2500 x 1.5min = est time remaining), I just don't know how to write into the query as a new column. Here is where my query is at now:
SELECT COUNT (UNITS) AS Orders_Remaining
FROM ORDERS
WHERE UNITS BETWEEN '0001' and '2500'
Do you mean this?
SELECT COUNT (UNITS) AS Orders_Remaining, COUNT(UNITS) * 1.5 AS Minutes_Remaining
FROM ORDERS
WHERE UNITS BETWEEN '0001' and '2500'