consider this sql
CREATE VIEW [dbo].[MyView1] ([ID],[VisitDate],[StartDate] ,[EndDate],[MyCount])
WITH SCHEMABINDING
AS
SELECT id, VisitDate,dateadd(dd,-10,VisitDate),dateadd(dd,10,VisitDate),
count_BIG(*)as MyCount
FROM dbo.Visits2
group by id,VisitDate
I am trying to create a clustered index on this view on id,VisitDate.I am getting the following error.
Cannot create the clustered index 'IX_!!' on view 'CI_DB.dbo.MyView4'
because the select list of the view contains an expression on result of
aggregate function or grouping column.
Consider removing expression on result of aggregate function or
grouping column from select list.
This is a known issue since 2006.
If you have an aggregation in an indexed view, and both a field and an expression applied to the field are in the GROUP BY (which I'm assuming you just left out of your sample code), the engine won't allow you to create it.
There are some workarounds but they aren't very straightforward. Basically you need to fool the engine into thinking the fields are different.
That's a pretty clear error message, your view is not one that can be indexed. THere are many many conditions on what kinds of views can be indexed.
Changed the sql to
CREATE VIEW [dbo].[MyView2] ([ID],[VisitDate],[StartDate] ,[EndDate],[MyCount])
WITH SCHEMABINDING
AS
SELECT id, VisitDate,
dateadd(day,duration,VisitDate) startdate
,dateadd(day,duration,VisitDate) enddate,
count_BIG(*)as MyCount
FROM dbo.Visits3
group by id,VisitDate,dateadd(day,duration,VisitDate),dateadd(day,duration,VisitDate)
GO
Seems like you cant specify a direct value like 10 inside the function and group by clause.Now it works!!
Related
Here's my situation, I have a table of values that is used to create various reports. I need an ORDER BY in order to group the info the way I need it.
SELECT
id, indate, group, lase, first, rank
FROM
this_table
WHERE
group = 'SomeGroup'
ORDER BY
last, first, indate
I can't use a view because it won't allow the order by. I was hoping I could create a stored procedure to return the result table I want, but without the extra return value.
I've read the comments, and I understand what a view is.
I guess the real problem is that I need to get the output into an Excel sheet, and I can only import Views, however I need the data sorted in my output.
A view is a passive object that just behaves like a table, but is really the result of a query (un-ordered, as you noticed). The view does do anything by itself. It's when you retrieve the data from the view that you apply your ORDER BY condition(s). The standard way you'd get data out would be by putting your logic in a stored procedure. Alternatively, if you are querying the data ad hoc, you don't even need to use a procedure.
Create View MyView as
SELECT id, indate, group, lase, first, rank
FROM this_table
WHERE group = 'SomeGroup';
then
select * from MyView
order by last, first, indate;
use library
go
create view V_booksOut3
as
SELECT
(select Book.Book_Title from Book where LB.B_ID=Book.Book_ID) as 'Book_Title',
L.Loaner_FName,
L.Loaner_Lname,
L.Loaner_Phone,
L.Loaner_Email,`enter code here`
LB.bookDueDate
FROM Loaner L
inner join Loaner_Book LB
ON L.Loaner_ID=LB.L_ID
WHERE LB.isActive = 1
ORDER BY L.Loaner_LName;
--I keep running into this error, but it fades once I remove the last to lines and try to create a view.
I do not wish to use the top/for xml keywords, but I want this view created with this query.
SQL tables and result sets represent unordered sets, unless an ORDER BY is explicitly included. This includes subqueries as well. So, the results from a subquery are unordered -- they have to be. It simply does not make sense to have an ORDER BY.
Some databases relax this restriction. However, SQL Server is quite explicit about it:
The SELECT clauses in a view definition cannot include the following:
An ORDER BY clause, unless there is also a TOP clause in the select
list of the SELECT statement System_CAPS_ICON_important.jpg Important
The ORDER BY clause is used only to determine the rows that are
returned by the TOP or OFFSET clause in the view definition. The ORDER
BY clause does not guarantee ordered results when the view is queried,
unless ORDER BY is also specified in the query itself.
Please remove Order by clause from inner query and put it outside or you've to have Top clause in Inner query. you will surely got your solution, happy sql bro :)
actually when you created view, you can use that in query, so if u can use this in query then you surely apply order by on created view, means view will be created as raw table without order by, then you apply order by clause on that created dataset view.
Hope it will clear confusion.
My task is to optimize this query:
Declare #sumBalance NUMERIC = (select SUM(CURRENT_BALANCE) as Balance
from dbo.ACCOUNT_DETAILS)
select #sumBalance
I've read that the best solution for aggregation functions is using indexed views instead of tables.
I've created the view with SCHEMABINDING:
CREATE VIEW dbo.CURRENT_BALANCE_VIEW
WITH SCHEMABINDING
AS
SELECT id,CURRENT_BALANCE
FROM dbo.ACCOUNT_DETAILS
After that I've created 2 indexes:
The first for ID
CREATE UNIQUE CLUSTERED INDEX index_ID_VIEW ON dbo.View(ID);
The second for CURRENT_BALANCE my second one column
CREATE NONCLUSTERED INDEX index_CURRENT_BALANCE_VIEW
ON dbo.CURRENT_BALANCE_VIEW(ID);
And here I got troubles with new query:
Declare #sumBalance NUMERIC = (select SUM(CURRENT_BALANCE) as Balance
from dbo.CURRENT_BALANCE_VIEW)
select #sumBalance
New query doesn't use view
http://i.stack.imgur.com/jlPEd.png
Somehow my indexes were added to the folder Statistics
Look in another post
I don't understand why I can see index 'index_current_balance' cause there is no such an index in the table
Look in another post
P.S. Already tried create index in the table and it helped. It made query works faster from 0.2 Es.operator cost to 0.009 but anyway it must be faster.
p.s.s Sorry for making you click on the link, my reputation doesn't allow me to past images properly =\
p.s.s.s Working with SQL Server 2014
p.s.s.s.s Just realized that I don't need to sum 0-s. Expected them grom function.
Thanks in advance.
if you use Standard Edition of SQL-Server you have to use the NOEXPAND-Hint in order to use the index of a view.
For example:
SELECT *
FROM dbo.CURRENT_BALANCE_VIEW (NOEXPAND);
This query:
Declare #sumBalance NUMERIC = (select SUM(CURRENT_BALANCE) as Balance
from dbo.ACCOUNT_DETAILS);
select #sumBalance;
is not easy to optimize. The only index that will help it is:
create index idx_account_details_current_balance on account_details(current_balance);
This is a covering index for the query, and can be used for the SUM(). However, the index still needs to be scanned to do the SUM(). Scanning the index should be faster than scanning the table because it is likely to be much smaller.
SQL Server 2012+ has a facility called columnstore indexes that would have the same effect.
The advice for using indexed views for aggregation functions doesn't seem like good advice. For instance, if the above query used MIN() or MAX(), then the above index should be the optimal index for the query, and it should run quite fast.
EDIT:
Your reference article is quite reasonable. If you want to create an indexed view for this purpose, then create it with aggregation.
CREATE VIEW dbo.CURRENT_BALANCE_VIEW
WITH SCHEMABINDING
AS
SELECT SUM(CURRENT_BALANCE) as bal, COUNT_BIG(CURRENT_BALANCE) as cnt
FROM dbo.ACCOUNT_DETAILS;
This is a little weird, because it returns one row. I think the following will work:
create index idx_account_details on current_balance_view(bal);
If not, you may need to introduce a dummy column for the index.
Then:
select *
from dbo.current_balance_view;
should have the precomputed value.
So, I just found out that SQL Server 2008 doesn't let you index a view with a CTE in the definition, but it allows you to alter the query to add with schemabinding in the view definition. Is there a good reason for this? Does it make sense for some reason I am unaware of? I was under the impression that WITH SCHEMABINDINGs main purpose was to allow you to index a view
new and improved with more query action
;with x
as
(
select rx.pat_id
,rx.drug_class
,count(*) as counts
from rx
group by rx.pat_id,rx.drug_class
)
select x.pat_id
,x.drug_class
,x.counts
,SUM(c.std_cost) as [Healthcare Costs]
from x
inner join claims as c
on claims.pat_id=x.pat_id
group by x.pat_id,x.drug_class,x.counts
And the code to create the index
create unique clustered index [TestIndexName] on [dbo].[MyView]
( pat_id asc, drug_class asc, counts asc)
You can't index a view with a CTE. Even though the view can have SCHEMABINDING. Think of it this way. In order to index a view, it must meet two conditions (and many others): (a) that it has been created WITH SCHEMABINDING and (b) that it does not contain a CTE. In order to schemabind a view, it does not need to meet the condition that it does not contain a CTE.
I'm not convinced there is a scenario where a view has a CTE and will benefit from being indexed. This is peripheral to your actual question, but my instinct is that you are trying to index this view to magically make it faster. An indexed view isn't necessarily going to be any faster than a query against the base tables - there are restrictions for a reason, and there are only particular use cases where they make sense. Please be careful to not just blindly index all of your views as a magic "go faster" button. Also remember that an indexed view requires maintenance. So it will increase the cost of any and all DML operations in your workload that affect the base table(s).
Schemabinding is not just for indexing views. It can also be used
on things like UDFs to help persuade determinism, can be used on
views and functions to prevent changes to the underlying schema, and
in some cases it can improve performance (for example, when a UDF is
not schema-bound, the optimizer may have to create a table spool to
handle any underlying DDL changes). So please don't think that it is
weird that you can schema-bind a view but you can't index it.
Indexing a view requires it, but the relationship is not mutual.
For your specific scenario, I recommend this:
CREATE VIEW dbo.PatClassCounts
WITH SCHEMABINDING
AS
SELECT pat_id, drug_class,
COUNT_BIG(*) AS counts
FROM dbo.rx
GROUP BY pat_id, drug_class;
GO
CREATE UNIQUE CLUSTERED INDEX ON dbo.PatClassCounts(pat_id, drug_class);
GO
CREATE VIEW dbo.ClaimSums
WITH SCHEMABINDING
AS
SELECT pat_id,
SUM(c.std_cost) AS [Healthcare Costs],
COUNT_BIG(*) AS counts
FROM dbo.claims
GROUP BY pat_id;
GO
CREATE UNIQUE CLUSTERED INDEX ON dbo.ClaimSums(pat_id);
GO
Now you can create a non-indexed view that just does a join between these two indexed views, and it will utilize the indexes (you may have to use NOEXPAND on a lower edition, not sure):
CREATE VIEW dbo.OriginalViewName
WITH SCHEMABINDING
AS
SELECT p.pat_id, p.drug_class, p.counts, c.[Healthcare Costs]
FROM dbo.PatClassCounts AS p
INNER JOIN dbo.ClaimSums AS c
ON p.pat_id = c.pat_id;
GO
Now, this all assumes that it is worthwhile to pre-aggregate this information - if you run this query infrequently, but the data is modified a lot, it may be better to NOT create indexed views.
Also note that the SUM(std_cost) from the ClaimSums view will be the same for every pat_id + drug_class combination, since it's only aggregated to pat_id. I guess there might be a drug_class in the claims table that should be part of the join criteria too, but I'm not sure. If that is the case, I think this could be collapsed to a single indexed view.
can we use order by clause in view in sql server 2005?
CREATE VIEW vw_authors
AS
SELECT TOP 10 PERCENT *
FROM dbo.authors
Group by au_id
ORDER BY au_fname
Yes and no. You cannot use order by in the view itself to specify the order. You can use it for row selection, such as with top 10. From the MSDN online docs:
The SELECT clauses in a view definition cannot include the following:
COMPUTE or COMPUTE BY clauses;
An ORDER BY clause, unless there is also a TOP clause in the select list of the SELECT statement (a);
The INTO keyword;
The OPTION clause;
A reference to a temporary table or a table variable.
(a) The ORDER BY clause is used only to determine the rows that are returned by the TOP clause in the view definition. The ORDER BY clause does not guarantee ordered results when the view is queried, unless ORDER BY is also specified in the query itself.
Yes you can.
CREATE VIEW vw_authors
AS
SELECT TOP 10 PERCENT *
FROM dbo.authors
WHERE au_fname='John'
However, ORDER BY is not valid. A view creates a dynamic result set which can then be queried in the same way as a table can. When querying a view you can then ORDER BY:
SELECT au_fname
FROM vw_authors
ORDER BY au_fname
Here's a nice Overview of Views in SQL Server 2005. As noted in the article, the views can be indexed so that queries of the view can be efficiently ordered with an ORDER BY. Also, see this Microsoft article on indexed views.
The summary answer: no, you can't use ORDER BY when creating a view, but you can index the view and use a fast ORDER BY on queries of that view.
Hope this helps. Good luck with your project :-)