Reputation: 46908
Suppose I have a view that rolls up data via a GROUP BY
clause:
CREATE VIEW InvoiceAmountsByCustomer AS
SELECT
Customer.CustomerID,
SUM(Invoice.TotalAmount) AS TotalInvoiceAmount
FROM
Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
GROUP BY Customer.CustomerID
Now, suppose I want the view to restrict which invoices are included in the total based on a date range. To illustrate (pretending {From Date}
and {To Date}
contain the date range):
CREATE VIEW InvoiceAmountsByCustomer AS
SELECT
Customer.CustomerID,
SUM(Invoice.TotalAmount) AS TotalInvoiceAmount
FROM
Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
WHERE
Invoice.Date BETWEEN {From Date} AND {To Date}
GROUP BY Customer.CustomerID
What do I replace {From Date}
and {To Date}
with so that I can pass their values (directly or indirectly) to the view? For example, is it possible to associate these values with the current session?
CREATE VIEW InvoiceAmountsByCustomer AS
SELECT
Customer.CustomerID,
SUM(Invoice.TotalAmount) AS TotalInvoiceAmount
FROM
Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
WHERE
Invoice.Date BETWEEN GetUserDefinedSessionValue('From Date') AND GetUserDefinedSessionValue('To Date')
GROUP BY Customer.CustomerID
where GetUserDefinedSessionValue
is an imaginary function that returns values associated with the current session. Another imaginary function, SetUserDefinedSessionValue
would be called by the client prior to querying the view:
SetUserDefinedSessionValue('From Date', ...)
SetUserDefinedSessionValue('To Date', ...)
SELECT * FROM InvoiceAmountsByCustomer
My imaginary example is only meant to illustrate one way I envision these values being passed to the view.
Note: This is a trivial example and the real situation is much more complex, preventing me from executing a GROUP BY
query directly by the client.
Upvotes: 2
Views: 9329
Reputation: 29
An old thread, but I was browsing for an answer to this particular dilema my self, when it suddenly struck me that maybe the simplest way is the best.
Soulution 1: Skip the view entirely and write the complete sql in your code. Then you can declare parameteres as you'd like. Unless you are using indexed views there is not much difference between select * from 'view' and the entire select statement with the declare options.
Solution 2: Instead of using view, why not just create a procedure? This is less flexible, but if you plan on using select * from ' view ' It'll do the same thing.
CREATE proc dbo.ViewDates @from_date datetime, @to_date datetime AS
SELECT
Customer.CustomerID,
SUM(Invoice.TotalAmount) AS TotalInvoiceAmount FROM
Customer LEFT OUTER JOIN Invoice ON Customer.CustomerID = Invoice.CustomerID
WHERE
Invoice.Date BETWEEN @from_date AND @to_date GROUP BY Customer.CustomerID
Then, instead of select * :
exec dbo.ViewDates @from_date = '20120101', @to_date = '20120930'
You may need to format the dates by using @from_date = convert(datetime,'desired datestring', desired date format)
I.e.
exec dbo.ViewDates @from_date = convert(datetime, '20120101',112), @to_date = convert(datetime,'20120930',112)
Upvotes: 2
Reputation: 15075
Here is one solution:
CREATE TABLE dbo.ViewDates (theDate DATETIME)
To query the database:
TRUNCATE TABLE viewDates
INSERT INTO viewDates VALUES (@fromDate)
INSERT INTO viewDates VALUES (@toDate)
To tweak the view
JOIN (select min(thedate) as StDate,max(theDate) as EnDate ) dt
ON invoice.date BETWEEN dt.StDate and dt.EndDate
Note that this will only work for one user at a time, if you need multiple users, you will need to add a user-id to the table, populate it, and adjust the query a bit...
Upvotes: 0
Reputation: 166396
It is possible to call User Defined Functions within a view, yes, but I would rather use a User Defined Table Function, where you pass in the parameters you require, and this in turn returns the data you wish for.
Upvotes: 3