Reputation: 3448
I am trying return design an SQL View
which returns TOP 3
records from a table in ascending order considering NULL
values in the table as the largest value so that I can discard the null values from top 3 results if there are more than three records.
I was able to successfully do it using following query but for reasons it is misbehaving w.r.t the third record is that if the third and fourth record in my table are same then my view is returning a NULL value are the third record which is kind of weird.
For Example Consider I have a column in my table named Grades
with values 23,45,19,35,35
and when I run my view it should return top 3 values in ascending order which are 19,23,35
but for some reasons my query returns 19,23,NULL
and the query works fine if my third record that is 35 is distinct ie if the Grades
are 23,45,19,35,40
then it works fine and returns 19,23,35
My Query is as follows
CREATE VIEW [dbo].[test]
AS
SELECT distinct
CC.Grades,
CC.Term,
FROM CanadianCrudes CC
CROSS APPLY (SELECT TOP 3 Grades
FROM CanadianCrudes iCC
WHERE CC.Term = iCC.Term
ORDER BY case
when iCC.Grades is null
then 1
else 0 end, iCC.Grades asc ) iCC
Upvotes: 0
Views: 100
Reputation: 69554
Important Note
You might have ordered results in a View's Definition but it does not guarantee ordered result when you actually select from view.
In your case it will pick the tops 3 values for each Grade but the order in which results and returned and displayed is not guaranteed, Unless you use Order By in your select statement when selecting from view.
Test Data
DECLARE @TABLE TABLE(ID INT)
INSERT INTO @TABLE VALUES
(1), (2),(3),(5),(NULL),(NULL)
Query
SELECT *
FROM @TABLE
ORDER BY CASE WHEN ID IS NULL THEN 100000 ELSE ID END ASC
Result Set
╔══════╗
║ ID ║
╠══════╣
║ 1 ║
║ 2 ║
║ 3 ║
║ 5 ║
║ NULL ║
║ NULL ║
╚══════╝
Upvotes: 1
Reputation: 1063
Assuming your grades have a limit to how high they can go could you use an isnull in your orderby and set a default high value for null occurences and a tie breaker for when two values have the same rank (e.g 35)
e.g
CREATE VIEW [dbo].[test]
AS
SELECT distinct
CC.Grades,
CC.Term,
FROM CanadianCrudes CC
CROSS APPLY (SELECT TOP 3 Grades
FROM CanadianCrudes iCC
WHERE CC.Term = iCC.Term
ORDER BY isnull(iCC.Grades, 150), ID
Upvotes: 2