tags:

views:

38

answers:

3

I have query like that:

(as You see I'd like to retrieve 50% of total rows or first 100 rows etc)

//@AllRowsSelectType is INT

 SELECT TOP (
    case @AllRowsSelectType
        when 1 then 100 PERCENT 
        when 2 then 50 PERCENT
        when 3 then 25 PERCENT
        when 4 then 33 PERCENT
        when 5 then 50
        when 6 then 100
        when 7 then 200 
    end
            ) ROW_NUMBER() OVER(ORDER BY [id]) AS row_num, a,b,c etc

why have I the error : "Incorrect syntax near the keyword 'PERCENT'." on line "when 1 [...]"

+4  A: 

The syntax for TOP is:

TOP (expression) [PERCENT]
[ WITH TIES ]

The reserved keyword PERCENT cannot be included in the expression. Instead you can run two different queries: one for when you want PERCENT and another for when you don't.

If you need this to be one query you can run both queries and use UNION ALL to combine the results:

SELECT TOP (
    CASE @AllRowsSelectType
        WHEN 1 THEN 100
        WHEN 2 THEN 50
        WHEN 3 THEN 25
        WHEN 4 THEN 33 
        ELSE 0
    END) PERCENT
    ROW_NUMBER() OVER(ORDER BY [id]) AS row_num, a, b, c, ...
UNION ALL
SELECT TOP (
    CASE @AllRowsSelectType
        WHEN 5 THEN 50
        WHEN 6 THEN 100
        WHEN 7 THEN 200
        ELSE 0
    END)
    ROW_NUMBER() OVER(ORDER BY [id]) AS row_num, a, b, c, ...
Mark Byers
+2  A: 

You're also mixing two different types of use. The other is.

DECLARE @ROW_LIMT int

IF @AllRowsSelectType < 5
    SELECT @ROW_LIMIT = COUNT(*)/@AllRowsSelectType FROM myTable -- 100%, 50%, 33%, 25%
ELSE
    SELECT @ROW_LIMIT = 50 * POWER(2, @AllRowsSelectType - 5) -- 50, 100, 200...

WITH OrderedMyTable
(
  select *, ROW_NUMBER() OVER (ORDER BY id) as rowNum
  FROM myTable
)
SELECT * FROM OrderedMyTable
WHERE rowNum <= @ROW_LIMIT
Jon Hanna
"TOP can only take a literal" Are you sure? According to the documentation TOP takes an expression.
Mark Byers
@Mark Yep, I saw your answer and tested and you are correct. Editted to still show the ROW_NUMBER() using approach.Could SQLServer always put expressions in TOP. I remember being unhappy that I couldn't once upon a time, but that would have been around the time of SQLServer7 at the latest.
Jon Hanna
You're right. It works since SQL Server 2005: http://msdn.microsoft.com/en-US/library/ms189463%28v=SQL.90%29.aspx. In SQL Server 2000 it requires a literal. http://msdn.microsoft.com/en-us/library/aa259187%28v=SQL.80%29.aspx
Mark Byers
Thanks. It's easier to keep track of new stuff added (like the way my answer uses a CTE, which is so much easier than the way one had to do so before they were introduced), than restrictions being loosened.Nice to see TOP is more flexible, though I'd still prefer if it had LIMIT and OFFSET like PostgreSQL; so much more flexible and concise, especially when it comes to OFFSET being other than zero.
Jon Hanna
A: 

You could do:

select top (CASE @FilterType WHEN 2 THEN 50 WHEN 3 THEN 25 WHEN 4 THEN 33 ELSE 100 END) percent * from
(select top (CASE @FilterType WHEN 5 THEN 50 WHEN 6 THEN 100 WHEN 7 THEN 200 ELSE 2147483647 END) * from
<your query here>
) t
) t

Which may be easier to read.

Damien_The_Unbeliever