Use Multi-Line Table Function or Stored Procedure
I am in the process of rewriting an Access database and I have some awful MS Access queries that I need to rewrite. They basically consist of the following set up
SELECT *
FROM Query1, Query2, Query,...
These queries are used in 2 existing databases and typically consist of a Count/Sum of data. Then we use the totals for reporting. Most of the subqueries are like this or something similar
SELECT Count(Account), Reason, Sum(Amount)
FROM table1
GROUP BY Reason
This is easy enough to rewrite and that isn't my problem. My problem is that I have about 20-30 of these queries that need to be rewritten. One of the requests that the users have now is to be have the option to get the Counts of the accounts as well as the List of accounts that make up the total. So now 开发者_StackOverflow中文版my 20-30 queries double because they want the lists as well.
So I am trying to determine the best way to design this to be able to provide the count or list for any particular day they want
I was thinking of creating a multi-statement table function to do this but I don't know if that would be better than a stored proc or a view or anything else
I created the following function which allows them to search by any date and they can get either the list of accounts or the counts.
CREATE FUNCTION [udf_GeBreakdown]
(
@BusinessDate datetime
, @ListOfAccounts bit
)
RETURNS @TableCount
TABLE
(
Account int, ReasonName varchar(50), Amount money
)
AS
BEGIN
DECLARE @PreviousDate smalldatetime
SET @PreviousDate = udf_GetNextImportDate(@BusinessDate, -1);
IF @ListOfAccounts = 0
BEGIN
INSERT INTO @TableCount
SELECT Count(Account), R.ReasonName, Sum(Amount)
FROM Debs.Resolved RS
INNER JOIN Debs.Reason R
ON RS.ReasonId = R.ReasonId
WHERE RS.DebitDate = @PreviousDate
AND RS.StatusId NOT IN (15, 17)
GROUP BY R.ReasonName
END
ELSE
BEGIN
INSERT INTO @TableCount
SELECT Account, R.ReasonName, Amount
FROM Debs.Resolved RS
INNER JOIN Debs.Reason R
ON RS.ReasonId = R.ReasonId
WHERE RS.DebitDate = @PreviousDate
AND RS.StatusId NOT IN (15, 17)
END
RETURN
END
I don't know if this is a waste of time doing it this way or if I should just provide a list of accounts and then get my Count/Sum when I query this. I am looking for some help and or direction on how best to proceed with this.
Performance is going to be an issue in this multi-statement UDF.
If you read from the system more than you write, I would try creating an indexed view similar to the following.
CREATE VIEW V1 WITH SCHEMABINDING AS
SELECT RS.DebitDate, Account, R.ReasonName, Amount
FROM Debs.Resolved RS
INNER JOIN Debs.Reason R
ON RS.ReasonId = R.ReasonId
WHERE RS.StatusId NOT IN (15, 17)
CREATE INDEX X on V1 -- based on usage
Then, use the following statement in a SP or single statement UDF to get the list of accounts. The statement becomes pretty trivial at that point. (you will have to do your previous day logic here...don't store that function in the view)
SELECT Count(Account), ReasonName, Sum(Amount)
FROM V1 with(noexpand)
GROUP BY DebitDate, ReasonName -- or use DebitDate in the where clause
I would still try this if your system is write intensive, however this indexed view will slow down inserts on the tables that are schemabound to it. Indexing views does come at a cost so you might be well served just creating a normal view.
精彩评论