Order by error in create view in SQL Server - sql

I'm trying to create this view in SQL Server:
CREATE VIEW tblSanPham_VIEW
AS
SELECT TenSP, MaDanhMuc, Mamau
FROM tblSanPham
ORDER BY MaSP DESC
I'm getting this error:
Msg 1033, Level 15, State 1, Procedure tblSanPham_VIEW, Line 6 [Batch Start Line 47]
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.

SQL Server doesn't support ORDER BY inside a view. This happens to remove the possibility of a "double sort" where the view defines a sorting order then the application requests a different sort order when the view is accessed.
In fact, you can use it if you add TOP:
CREATE VIEW tblSanPham_VIEW
AS
SELECT TOP 100 PERCENT
TenSP,
MaDanhMuc,
Mamau
FROM tblSanPham
ORDER BY MaSP DESC
In this case, the view gets created without an error but if you try to pull data from it ORDER BY is completely ignored.
Try using ORDER BY clause to the queries that pull data from your view, not to the code of the view itself.

by adding a TOP clause
CREATE VIEW tblSanPham_VIEW
AS
SELECT TOP (99.9999) PERCENT TenSP,
MaDanhMuc,
Mamau
FROM tblSanPham
ORDER BY
MaSP DESC
OR if you just select from the view, without an ORDER BY clause:
CREATE VIEW tblSanPham_VIEW
AS
SELECT TenSP,
MaDanhMuc,
Mamau
FROM tblSanPham
Then:
SELECT *
FROM dbo.tblSanPham_VIEW
ORDER BY
MaSP DESC

Related

SQL ORDER BY in SQL table returning function

so I have simple function trying to get two fields from database. I'm trying to use order by for the results however I cannot use ORDER BY in return clause.
It tells me
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
Is is it possible to use ORDER BY in RETURN statement? I would like to avoid using order by when executing the function.
CREATE FUNCTION goalsGames1 () RETURNS TABLE
AS RETURN(
SELECT MAX(goals_scored) goals,
no_games
FROM Player
GROUP BY no_games
ORDER BY no_games DESC )
One trick to skip this error is using top as it is mentioned in the error message:
CREATE FUNCTION goalsGames1 () RETURNS TABLE
AS RETURN(
SELECT Top 100 Percent MAX(goals_scored) goals,
no_games
FROM Player
GROUP BY no_games
ORDER BY no_games DESC )
I would like to avoid using order by when executing the function.
If you are using the function and want the results in a particular order, then you need to use ORDER BY.
This is quite clearly stated in the documentation:
The ORDER clause does not guarantee ordered results when a SELECT query is executed, unless ORDER BY is also specified in the query.
use order by intimes of selection your function not in times of creation
so use here in select * from goalsGames1 order by col
and your error tells you where order by is invalid
You cannot order by inside a function, the idea is to order the resultset returned by the function.
select *
from dbo.goalsGames1()
order by no_games
Even if you would order by inside the function, there is no guaranty that this ordering would be preserved when the resultset is returned. The executing query (select * from functionname) has to be responsible for setting the order, not the function or view.
Who ever receives the rows is the only one that can order them, so in this case, the select * from goalsGames1() is the receiver, and this query has to order the results.

Jet-SQL to TSQL

In MS Access 2010 I have the following code:
SELECT
[Teile-LF-Beziehungen].Lieferant,
COUNT([Teile-LF-Beziehungen].Lieferant) AS [Anz Teile],
First([Teile-LF-Beziehungen].Name) AS Name
FROM
[Teile-LF-Beziehungen]
GROUP BY
[Teile-LF-Beziehungen].Lieferant
ORDER BY
COUNT([Teile-LF-Beziehungen].Lieferant) DESC;
I want to put that query into SQL Server, because MS Access should be only the frontend.
But in SQL Server I can't use the ORDER in a view. But why? I don't understand it. The code I want to use in SQL Server:
SELECT
[Lieferant],
COUNT([Lieferant]) AS [Anz Teile],
MIN([Name]) AS [Name]
FROM
[dbo].[VIEW_Teile-LF-Beziehungen]
GROUP BY
[Lieferant]
ORDER BY
COUNT([Lieferant]) DESC;
I know it don't work. But is there any way to incur a MS Access query 1:1 to a SQL Server query (view)?
Only the outermost select can use an order by (but you might state a TOP 100 percent to trick this out). Therefore it is perfectly OK, that at VIEW does not allow this.
Many people think, that tables have kind of an implicit order (as you see the result ordered), but this is random... The next call could lead to a different sorting.
There is another way using ROW_NUMBER with OVER(ORDER BY). The result is delivered in this order and the order is guaranteed as long the orderby is sorting after unique values.
EDIT
Sorry my first attempt was to quick. The ROW_NUMBER was not allowed due to the grouping
This should work:
SELECT tbl.Lieferant
,tbl.[Anz Teile]
,tbl.Name
,ROW_NUMBER() OVER(ORDER BY tbl.[Anz Teile] DESC) AS Sort
FROM
(
SELECT [Lieferant]
,COUNT([Lieferant]) AS [Anz Teile]
,MIN([Name]) AS [Name]
FROM [dbo].[VIEW_Teile-LF-Beziehungen]
GROUP BY [Lieferant]
) AS tbl;
EDIT2
This SELECT can be placed within a VIEW, just place your CREATE VIEW YourViewName AS before the SELECT and execute. After this you'll be able to do a SELECT * FROM YourViewName to get a sorted list.
BUT
As stated in many places: The best is the outermost ORDER BY in any case!
ORDER BY doesnt work inside the view. SQL server is free to return the rows anyway he want if you dont include the order by when calling the View
So you need
SELECT *
FROM yourView
ORDER BY yourField
EDIT: Im saying if your view is
CREATE VIEW yourView AS
SELECT
[Lieferant],
COUNT([Lieferant]) AS [Anz Teile],
MIN([Name]) AS [Name]
FROM
[dbo].[VIEW_Teile-LF-Beziehungen]
GROUP BY
[Lieferant];
Then you call your View like this
SELECT *
FROM yourView
ORDER BY [Anz Teile]

Does a select on a view keep the order by from the view?

When view is created including an ORDER BY clause, will that order be maintained when using SELECT * FROM VIEW?
Or is it necessary to state SELECT * FROM VIEW ORDER BY ?
You would need an order by on the outer query to guarantee that the rows are returned in the order you want.
If you run a select * from view query against the view without a where clause, it is likely that the rows would be returned in the order defined in the order by. But that's not something that you should depend on.
I dont believe you can create a view using order by. You need to select from the view and then order by in that statement.

How to sort within a sql view

I've created a sql view and I need to sort the results of select by using the ORDER BY on 4 fields, but I'm getting message that ORDER BY cannot be used in views unless I use TOP.
Can someone explain why TOP is needed, and does someone have a workaround for sorting in a sql view?
Thanks.
you don't need to sort a view. a view is like a table so you sort it when you select from it:
select * from yourView order by yourColumns
There is no guarantee the output of the view will be ordered
Only the outermost ORDER BY applies for result sets: not any inner ones. So only this ORDER BY can be guaranteed to work:
SELECT col1, col2, FROm MyView ORDER BY col2
You can add it to views or derived tables and it forces "intermediate materialisation" because the results have to be ordered. However, for SQL Server 2005 and above, you have to use TOP 2000000000 not TOP 100 PERCENT (except for that HF that Daniel Vassallo mentioned!)
Someone will use your view with a different order to that internally at some point too.
You can try:
CREATE VIEW View_Products
AS
SELECT ProductID, ProductName, UnitPrice, CreateDate FROM Products
Order by CreateDate DESC
OFFSET 0 ROWS
Would creating an index on the column with which you intend to sort the view help?

Why use Select Top 100 Percent?

I understand that prior to SQL Server 2005, you could "trick" SQL Server to allow use of an order by in a view definition, by also include TOP 100 PERCENT in the SELECT clause. But I have seen other code which I have inherited which uses SELECT TOP 100 PERCENT ... within dynamic SQL statements (used in ADO in ASP.NET apps, etc). Is there any reason for this? Isn't the result the same as not including the TOP 100 PERCENT?
It was used for "intermediate materialization (Google search)"
Good article: Adam Machanic: Exploring the secrets of intermediate materialization
He even raised an MS Connect so it can be done in a cleaner fashion
My view is "not inherently bad", but don't use it unless 100% sure. The problem is, it works only at the time you do it and probably not later (patch level, schema, index, row counts etc)...
Worked example
This may fail because you don't know in which order things are evaluated
SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1 AND CAST(foo AS int) > 100
And this may also fail because
SELECT foo
FROM
(SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1) bar
WHERE
CAST(foo AS int) > 100
However, this did not in SQL Server 2000. The inner query is evaluated and spooled:
SELECT foo
FROM
(SELECT TOP 100 PERCENT foo From MyTable WHERE ISNUMERIC (foo) = 1 ORDER BY foo) bar
WHERE
CAST(foo AS int) > 100
Note, this still works in SQL Server 2005
SELECT TOP 2000000000 ... ORDER BY...
TOP (100) PERCENT is completely meaningless in recent versions of SQL Server, and it (along with the corresponding ORDER BY, in the case of a view definition or derived table) is ignored by the query processor.
You're correct that once upon a time, it could be used as a trick, but even then it wasn't reliable. Sadly, some of Microsoft's graphical tools put this meaningless clause in.
As for why this might appear in dynamic SQL, I have no idea. You're correct that there's no reason for it, and the result is the same without it (and again, in the case of a view definition or derived table, without both the TOP and ORDER BY clauses).
...allow use of an ORDER BY in a view definition.
That's not a good idea. A view should never have an ORDER BY defined.
An ORDER BY has an impact on performance - using it a view means that the ORDER BY will turn up in the explain plan. If you have a query where the view is joined to anything in the immediate query, or referenced in an inline view (CTE/subquery factoring) - the ORDER BY is always run prior to the final ORDER BY (assuming it was defined). There's no benefit to ordering rows that aren't the final result set when the query isn't using TOP (or LIMIT for MySQL/Postgres).
Consider:
CREATE VIEW my_view AS
SELECT i.item_id,
i.item_description,
it.item_type_description
FROM ITEMS i
JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
ORDER BY i.item_description
...
SELECT t.item_id,
t.item_description,
t.item_type_description
FROM my_view t
ORDER BY t.item_type_description
...is the equivalent to using:
SELECT t.item_id,
t.item_description,
t.item_type_description
FROM (SELECT i.item_id,
i.item_description,
it.item_type_description
FROM ITEMS i
JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
ORDER BY i.item_description) t
ORDER BY t.item_type_description
This is bad because:
The example is ordering the list initially by the item description, and then it's reordered based on the item type description. It's wasted resources in the first sort - running as is does not mean it's running: ORDER BY item_type_description, item_description
It's not obvious what the view is ordered by due to encapsulation. This does not mean you should create multiple views with different sort orders...
If there is no ORDER BY clause, then TOP 100 PERCENT is redundant. (As you mention, this was the 'trick' with views)
[Hopefully the optimizer will optimize this away.]
I have seen other code which I have inherited which uses SELECT TOP 100 PERCENT
The reason for this is simple: Enterprise Manager used to try to be helpful and format your code to include this for you. There was no point ever trying to remove it as it didn't really hurt anything and the next time you went to change it EM would insert it again.
No reason but indifference, I'd guess.
Such query strings are usually generated by a graphical query tool. The user joins a few tables, adds a filter, a sort order, and tests the results. Since the user may want to save the query as a view, the tool adds a TOP 100 PERCENT. In this case, though, the user copies the SQL into his code, parameterized the WHERE clause, and hides everything in a data access layer. Out of mind, out of sight.
Kindly try the below, Hope it will work for you.
SELECT TOP
( SELECT COUNT(foo)
From MyTable
WHERE ISNUMERIC (foo) = 1) *
FROM bar WITH(NOLOCK)
ORDER BY foo
WHERE CAST(foo AS int) > 100
)
The error says it all...
Msg 1033, Level 15, State 1, Procedure TestView, Line 5 The ORDER BY
clause is invalid in views, inline functions, derived tables,
subqueries, and common table expressions, unless TOP, OFFSET or FOR
XML is also specified.
Don't use TOP 100 PERCENT, use TOP n, where N is a number
The TOP 100 PERCENT (for reasons I don't know) is ignored by SQL Server VIEW (post 2012 versions), but I think MS kept it for syntax reasons. TOP n is better and will work inside a view and sort it the way you want when a view is used initially, but be careful.
I would suppose that you can use a variable in the result, but aside from getting the ORDER BY piece in a view, you will not see a benefit by implicitly stating "TOP 100 PERCENT":
declare #t int
set #t=100
select top (#t) percent * from tableOf
Just try this, it explains it pretty much itself. You can't create a view with an ORDER BY except if...
CREATE VIEW v_Test
AS
SELECT name
FROM sysobjects
ORDER BY name
GO
Msg 1033, Level 15, State 1, Procedure TestView, Line 5 The ORDER BY
clause is invalid in views, inline functions, derived tables,
subqueries, and common table expressions, unless TOP, OFFSET or FOR
XML is also specified.