/*============================================================================
  File:     Top 100 Percent in SQL Server 2005.sql

  Summary:  In SQL Server 2005, TOP 100 Percent cannot be used to 
			to ORDER the data within a view. (1) Is there another way?
			and (2) do you really want to use it? Be sure to review
			the entire script.
  
  Date:     June 2006

  SQL Server Version: 9.00.2047.00 (SP1)
------------------------------------------------------------------------------
  Copyright (C) 2006 Kimberly L. Tripp, SYSolutions, Inc.
  All rights reserved.

  For more scripts and sample code, check out 
    http://www.SQLskills.com

  This script is intended only as a supplement to demos and lectures
  given by Kimberly L. Tripp.  
  
  THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF 
  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED 
  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  PARTICULAR PURPOSE.
============================================================================*/

USE northwind
go

-- These samples use the northwind database. You can backup and 
-- restore the northwind database from SQL Server 2000. 

CREATE VIEW OrderSubTotalsViewNOTOrdered 
AS
SELECT OD.OrderID,
	 SUM(CONVERT(money,(OD.UnitPrice
		*Quantity*(1-Discount)/100))*100) AS SubTotal
FROM [Order Details] AS OD
GROUP BY OD.OrderID
GO

CREATE VIEW OrderSubTotalsViewOrdered 
AS
SELECT TOP 100 PERCENT OD.OrderID,
	 SUM(CONVERT(money,(OD.UnitPrice
		*Quantity*(1-Discount)/100))*100) AS SubTotal
FROM [Order Details] AS OD
GROUP BY OD.OrderID
ORDER BY SubTotal DESC
go

SELECT * FROM dbo.OrderSubTotalsViewNOTOrdered 
ORDER BY SubTotal DESC
go

SELECT * FROM dbo.OrderSubTotalsViewOrdered
go

-- WAIT - this doesn't work in SQL Server 2005!!!
-- In SQL Server 2000, the TOP 100 PERCENT with ORDER BY
-- WORKED (as a trick) BUT, really - you shouldn't be able
-- to order data in a view so in SQL Server 2005 they have 
-- removed this "feature". So, do you have an option if
-- you REALLY want to have the data in a view ordered?

-- Yes - you can use a percentage that's NOT exactly possible
-- and SQL Server will round "up" to essentially 100 percent...
-- OR you can use a number that's WAY above the number of actual
-- rows in the table.

-- (this was a very clever idea from Meinrad Weiss - a fellow
--  RD in Switzerland... he came up with this after I said that 
--  the trick no longer worked... BUT, I'm still VERY hesitant to 
--  recommend this without making sure that you understand the 
--  implications... make sure to keep reading and test this entire 
--  script.)

CREATE VIEW OrderSubTotalsViewOrdered2 
AS
SELECT TOP 99.999 PERCENT OD.OrderID,
	 SUM(CONVERT(money,(OD.UnitPrice
		*Quantity*(1-Discount)/100))*100) AS SubTotal
FROM [Order Details] AS OD
GROUP BY OD.OrderID
ORDER BY SubTotal DESC
go

-- OR

-- (this next view using the MAX bigint value)
CREATE VIEW OrderSubTotalsViewOrdered3 
AS
SELECT TOP 9223372036854775807 OD.OrderID,
	 SUM(CONVERT(money,(OD.UnitPrice
		*Quantity*(1-Discount)/100))*100) AS SubTotal
FROM [Order Details] AS OD
GROUP BY OD.OrderID
ORDER BY SubTotal DESC
go

SELECT * FROM dbo.OrderSubTotalsViewNOTOrdered 
ORDER BY SubTotal DESC
go

SELECT * FROM dbo.OrderSubTotalsViewOrdered2
go

SELECT * FROM dbo.OrderSubTotalsViewOrdered3
go

-- No difference between these two... and if you're ONLY using this
-- to get a displayed set then you're OK BUT, I really want to 
-- STRONGLY urge you to use the ORDER BY when selecting from the view
-- AND NOT use this hint inside of a VIEW. In a lot of cases, this can
-- cause you excessive and unnecessary overhead.

-- Basically, if this view becomes relied upon for other uses, then
-- this ORDER BY will begin to cause you problems.

-- Compare the plans (showplan, Ctrl+k) of the two following 
-- queries and you'll see that the view which has the ORDER BY
-- in it has an extra step of ordering the data - which is NOT
-- necessary.

SELECT C.ContactName, Sub.* 
FROM OrderSubTotalsViewOrdered2 AS Sub
	JOIN Orders AS O ON O.orderid = Sub.Orderid
	JOIN Customers AS c ON c.customerid = o.customerid
WHERE C.City = 'Madrid'
ORDER BY SubTotal DESC 
go

SELECT C.ContactName, Sub.* 
FROM OrderSubTotalsViewNOTOrdered AS Sub
	JOIN Orders AS O ON O.orderid = Sub.Orderid
	JOIN Customers AS c ON c.customerid = o.customerid
WHERE C.City = 'Madrid'
ORDER BY SubTotal DESC
go