El *_*7eR 38 t-sql database sql-server view sql-server-2008-r2
我正在尝试使用ORDER BY子句创建视图.我已经在SQL Server 2012 SP1上成功创建它,但是当我尝试在SQL Server 2008 R2上重新创建它时,我收到此错误:
消息102,级别15,状态1,过程TopUsers,第11行
'OFFSET'附近的语法不正确.
创建视图的代码是
CREATE View [dbo].[TopUsersTest]
as
select
u.[DisplayName] , sum(a.AnswerMark) as Marks
From Users_Questions us inner join [dbo].[Users] u
on u.[UserID] = us.[UserID]
inner join [dbo].[Answers] a
on a.[AnswerID] = us.[AnswerID]
group by [DisplayName]
order by Marks desc
OFFSET 0 ROWS
Run Code Online (Sandbox Code Playgroud)
=====================
这是该图的屏幕截图

我想返回用户DisplayName和UserTotalMarks秩序这一结果说明,所以用最大的成果,用户与上顶.
Aar*_*and 72
我不确定你认为这ORDER BY是在完成什么?即使你不把ORDER BY视图的法律途径(通过添加例如TOP条款),如果你只是从视图,例如选择SELECT * FROM dbo.TopUsersTest;没有ORDER BY子句,SQL Server是自由地以最有效的方式返回行,从而赢得了"必然与您期望的订单相匹配.这是因为它ORDER BY被重载,因为它试图服务于两个目的:对结果进行排序并指示要包含哪些行TOP.在这种情况下,TOP总是获胜(虽然取决于选择扫描数据的索引,您可能会发现您的订单按预期工作 - 但这只是巧合).
为了实现您的目标,您需要将ORDER BY子句添加到从视图中提取数据的查询中,而不是视图本身的代码.
所以你的视图代码应该只是:
CREATE VIEW [dbo].[TopUsersTest]
AS
SELECT
u.[DisplayName], SUM(a.AnswerMark) AS Marks
FROM
dbo.Users_Questions AS uq
INNER JOIN [dbo].[Users] AS u
ON u.[UserID] = us.[UserID]
INNER JOIN [dbo].[Answers] AS a
ON a.[AnswerID] = uq.[AnswerID]
GROUP BY u.[DisplayName];
Run Code Online (Sandbox Code Playgroud)
这ORDER BY是没有意义的,所以甚至不应该包括在内.
为了说明,使用AdventureWorks2012,这是一个例子:
CREATE VIEW dbo.SillyView
AS
SELECT TOP 100 PERCENT
SalesOrderID, OrderDate, CustomerID , AccountNumber, TotalDue
FROM Sales.SalesOrderHeader
ORDER BY CustomerID;
GO
SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView;
Run Code Online (Sandbox Code Playgroud)
结果:
SalesOrderID OrderDate CustomerID AccountNumber TotalDue
------------ ---------- ---------- -------------- ----------
43659 2005-07-01 29825 10-4020-000676 23153.2339
43660 2005-07-01 29672 10-4020-000117 1457.3288
43661 2005-07-01 29734 10-4020-000442 36865.8012
43662 2005-07-01 29994 10-4020-000227 32474.9324
43663 2005-07-01 29565 10-4020-000510 472.3108
Run Code Online (Sandbox Code Playgroud)
你可以从该执行计划中看到TOP,并ORDER BY已完全忽略,而SQL Server的优化掉:

完全没有TOP操作员,没有任何排序.SQL Server完全优化了它们.
现在,如果您更改视图ORDER BY SalesID,那么您将恰好获得视图所述的排序,但只是 - 如前所述 - 巧合.
但是,如果您更改外部查询以执行ORDER BY您想要的:
SELECT SalesOrderID, OrderDate, CustomerID, AccountNumber, TotalDue
FROM dbo.SillyView
ORDER BY CustomerID;
Run Code Online (Sandbox Code Playgroud)
您可以按照自己的方式获得结果:
SalesOrderID OrderDate CustomerID AccountNumber TotalDue
------------ ---------- ---------- -------------- ----------
43793 2005-07-22 11000 10-4030-011000 3756.989
51522 2007-07-22 11000 10-4030-011000 2587.8769
57418 2007-11-04 11000 10-4030-011000 2770.2682
51493 2007-07-20 11001 10-4030-011001 2674.0227
43767 2005-07-18 11001 10-4030-011001 3729.364
Run Code Online (Sandbox Code Playgroud)
并且该计划仍然优化了视图中的TOP/ ORDER BY,但是添加了一种排序(以不小的代价,请注意)以呈现由CustomerID以下顺序排序的结果:

所以,故事的道德,不要把ORDER BY放在意见中.将ORDER BY放在引用它们的查询中.如果排序很昂贵,您可以考虑添加/更改索引以支持它.
Blu*_*eft 30
我已经成功地迫使视图被命令使用
SELECT TOP 9999999 ... ORDER BY something
Run Code Online (Sandbox Code Playgroud)
不幸的是,SELECT TOP 100 PERCENT由于这里的问题,使用不起作用.
从 Sql 2012 开始,您可以使用 OFFSET 在视图和子查询中强制排序
SELECT C.CustomerID,
C.CustomerName,
C.CustomerAge
FROM dbo.Customer C
ORDER BY CustomerAge OFFSET 0 ROWS;
Run Code Online (Sandbox Code Playgroud)
警告:这应该只用于小列表,因为即使视图上的进一步连接或过滤器减小其大小,OFFSET 也会强制评估完整视图!
没有好的方法可以真正且有充分的理由在没有副作用的情况下强制在视图中进行排序。
| 归档时间: |
|
| 查看次数: |
138013 次 |
| 最近记录: |