My customer is using MSAccess to read SQL Server Data.
Originally they created a linked table to the SQLServer base table,
then in Access, created a Query that aggregated and filtered.
Select f1,f2,sum(f3),sum(f4)
From linkedtablename
where fx = 'somevalue'
group by f1,f2
For security & performance reasons, I built simple a query in MSSQL to do the filtering & aggregating,
and asked the user to point to that instead, with a passthrough query.
So now they have and ODBC 'passthroughquery' doing a 'select * from MSSQLview'
However, MSAccess seems to be really struggling when we do anything with this passthrough.
e.g. Adding the passthrough to a new MSAccess query window takes forever.
Seems as if Access is doing some heavy reading of the source or source metadata each time we interact with it.
Running a select against the passthrough is also taking an age ... but with the aggregating being done by MSSQL, it should be a lot faster !?
So the question is, why does MSAccess struggle so much ?
Is Access trying to profile the source data even without an explicit 'select' being done ?
Or is it trying to read metadata every time we interact with the Passthrough ?
Ultimately, I am hoping that there is some configuration setting that will force Access to treat this like a 'standard' table !
If you use a PT query, keep in mind that if you use this as a source for a client query, then ZERO additional filtering can be used, or will work.
In other words?
A PT query is one of the fastest (high performance) ways to pull data. BUT ONLY if you do NOT attempt to add additional filtering. A PT query cannot be filtered by client side (well, it can, but ONLY after pulling the PT full query source).
As a result?
Use a linked view. They perform JUST as well as a stored procedure and a PT query, but they can and do respect client side filtering. So, for example you can build a client side query against that linked view with criteria, and ONLY the records matching that query are pulled down the network pipe.
this seems somewhat counter intuitive, but PT queries are fast, but they DO NOT respect additional filters client side (to be specific, you can filter against a pt query, but Access ONLY does so after pulling all records in the PT query). So, one would do VERY well to say avoid using a PT query to fill a combo box, or any thing else client side that will and does attempt to apply additional filtering and criteria.
To be crystal clear:
A PT query is great, but ONLY if you going to have the PT query do the filter in the first place. Additional filtering can be done, but that assumes the original PT query did not pull a lot of data in the first place. So a PT query rows pulled is what you WILL GET client side.
In 99% of cases, you are FAR better off to put that query in a linked view, and thus you are free to filter and add criteria to that view (even client side), and ONLY records meeting that criteria are pulled down the network pipe. this includes even using a client side query on that linked view. And this also includes basing a report on that linked view, and say you have VBA to add/provide a "where" clause to that report. (in this case, once again, Access will ONLY pull records based on that criteria. If you use a PT query for the report and attempt to filter - that filtering ONLY occurs AFTER all PT records been pulled.
So, PT queries cannot effective REDUCE bandwidth requirements to ANY lower then what the PT query returns in the first place. However, linked views DO allow and DO respect additional filters applied - even when done client side. As a result, a PT query is not all that useful unless the PT query has the criteria pre-defined and known ahead of time.
So, I would strong suggest you try/test/use a linked view.
In other words, put that sum and group by in a server side view and link to that.
Edit: and you CAN add the where clause to that view client side against that view.
However, because Fx is not a column, then you have to either add that column to the view, or create a stored procedure, and use it this way:
CREATE PROCEDURE [dbo].[GetMyGroupSum]
#fx nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT f1, f2, SUM(f3), SUM(f4)
FROM dbo.TheTableToQueryOn
WHERE fx = #fx
GROUP BY f1,f2
END
Now, create a PT query in Access. You code will then look like:
dim strFX as string
strFX = "somevalue"
currentdb.querydefs("MyPtQuery").sql = "EXEC GetMyGroupSum '" & strFX & "'"
You are now free to use the above query for a report, code or even launch a form based on that PT query.
In MOST cases you are better to use a view, but because the query does NOT return the column you need to filter on, then a PT query is the solution, but in most cases, it is not.
Related
I have a subform in form which is created from two linked SQL tables. I run the subform from a query. I have 2 left joins in these tables. Then I have multiply expression of two columns, each column from one table. Then I run it, everything works fine, but other can't open the subform. The error code is like this:
Access this expression is typed incorrectly or it is too complex to be evaluated. for example a numeric expression may contain too many complicated elements...
Often this will fail as the database starts to grow as well. Don't be afraid to use those complex queries but just create a static temporary table. It will ultimately be faster (lookup in a table vs multiple query calls) and easily bypass these complex embedded calculation calls.
PS
Sometimes I would create ComplexQueryA, then ComplexQueryB would use that as the datasource and do another calculation etc, but ultimately when my final results were done I would always dump into a static table otherwise the application would be way too slow!
I am attempting to combine two groupings(sum), EPL and POL and relabel them as something, say "Other GL". The current output is this. I've attempted adding a formula in the criteria but it is not working. I have also attempted adding another column in the design view with a formula alone.
The best way to "combine" data rows for grouping (i.e. sums) is to create a preliminary query which reassigns the individual source rows to a common value. Then use that query as the source for the other query(ies). (Such a preliminary query could be either a nested query -a.k.a. subquery-, or a saved query. I personally prefer saved queries since they can be edited and viewed using the standard Access Query Designer, whereas subqueries can only be edited as SQL text.)
Without other database schema or SQL statement to work with, all I can show is a SQL snippet showing the altered selection:
SELECT iif(Claims2.Grouping = 'EPL' Or Claims2.Grouping = 'POL', 'Other GL', Claims2.Grouping) As AltGrouping, ...
FROM Claims2
For what it's worth, the same iif() statement could also be inserted directly into the your query as a "calculated field"--within the query designer just copy and paste it into the Field cell in place of Grouping. But a saved query that adjusts labels preliminary to final queries can be reused and makes later queries simpler.
Is there a way to get the last run date from the cache refresh page for a SSRS report and have that displayed on the report? I'd like the user to know when the data was last refreshed.
You can query the ReportServer database directly to accomplish this:
SELECT MAX(els.TimeEnd) AS LastCacheRefresh
FROM dbo.ExecutionLogStorage AS els
INNER JOIN dbo.Catalog AS cat ON els.ReportID = cat.ItemID
WHERE els.RequestType = 2 --Refresh Cache
AND els.Status = 'rsSuccess'
AND cat.Name = 'MyReport'
Also FYI, Microsoft does not support querying the ReportServer database directly, which means fields/schema could change in later versions of SSRS.
Sorry to contribute to old thread, but wasn't finding a lot of hits on this question, so figured I'd add this:
If you include a calculated field in your source query, it is evaluated when the query is run and records along with the rest of your data. For example:
select
field1
, getdate() as QueryDateTime
from
SQLServerTable
and you can then use that value as min/max/first in your report (by definition is the same on every record).
This has to be done by the server dishing up the data, not as a calculated field in SSRS, because those are evaluated at run time, same as now() expression, or global execution time variable.
One downside of course is that you're recording that data and storing it, then having to retrieve a bunch of redundant data when pulling it, so it's not really efficient from a purist I/O perspective. I suspect the cost of one column of a single date value is not too much to worry about in most cases.
I have an a MySQL database. My database contains documents with a datetime column called "created". I want to group by day in order to have the document count per day. However, some days have zero documents and as a result they are not part of the output. For example I need '2001-01-01' to have a zero count if documents do not exist.
I am thinking of creating an extra table with the date range I am interested on and the to Do an outer join with my table. Then I can group by date to have my results.
Is there any better way of doing such a thing?
My SQL code:
Select date(created_at),c.text from Dates d left outer join classifier c on d.n=DATE(c.created_at)
where c.classifier="2014streamlrall"
and date(c.created_at)>='2014-03-01' and date(c.created_at)<='2014-05-01'
order by d.n;
The left join still does not work.
There is no better way for that in MySQL.
It lacks both a method to generate an arbitrary length resultset (similar to PostgreSQL's generate_series) and recursive SQL required to emulate such a method (which is used in SQL Server and Oracle).
Even on SQL Server, populating and keeping a table with 100 years worth of dates (which takes but a little more than 73K records) gives much better performance on reports similar to yours than using a generated resultset.
Is your real issue with having a create a row with '2001-01-01: 0'? If so, just wrap the MySQL with PHP and control your output with PHP. Then you just echo (or create an XML entry, whatever formatting you need) with the date and the result, even if it's 0. Even if you're currently know nothing about PHP, there are plenty of tutorials on how to run MySQL queries in PHP and output results. Good luck.
I have joined 5 tables and done transformation on these tables. Now I got a single table at the end. Now I want to perform sql query on this single table to filter records. But I don't know how to perform simple sql query on this table. I have attached a snap shot which shows the resulting table. How I get this resulting data set as the source? I want to populate my destination after filter out this data.
I am using SSIS 2008.
Click here to see the Table on which I want to perform a simple sql query
SELECT * FROM `first_table`
where `some_column` =
(
SELECT `*`
FROM second_table
WHERE
`some_column2`='something'
LIMIT 1
)
Try this code This will help. You can even use this to connect all those four tables with each other.
From the image you posted, it looks like you have a set of data in the dataflow you're trying to query against. You need to do one of two things at this point. Either you insert the data into a table in the database and use another data flow to query it, or you use use a conditional split (or multicast and conditional splits) to filter the rows down further from there.
Without more detail about what you're actually trying to accomplish, these are the recommendations I can determine.
You could send the rows into a record set destination, but you aren't able to query it like a regular table and you'd need some C#/VB skills to access it to do more than a FOR EACH loop.
Assuming your sql query that you want to run against the resulting table is simple, you can use a script component task. By simple, I mean, if it is of this nature:
SELECT * FROM T WHERE a = 'zz' and b = 'XX' etc.
However, if your query has self joins, then you would be better of dumping the outcome of joining those 5 tables in to a physical table, and go from there.
It appears that query is going to be real straight-forward; in that case using a script component would be helpful.
A separate question: It's advisable to do the sorting at the database level. You are using 5 sort tasks in your solution. Can you please elucidate the reason?