OK. This is similar to how Oracle handles it too. How about this?

class MSSQL3Adapter(MSSQLAdapter):
    def select_limitby(self, sql_s, sql_f, sql_t, sql_w, sql_o, limitby):
        if limitby:
            (lmin, lmax) = limitby
            return 'SELECT %s FROM (SELECT %s ROW_NUMBER() over (order by 
id) AS w_row, %s FROM %s%s%s) TMP WHERE w_row BETWEEN %i AND %s;' % 
(sql_f,sql_s,sql_f,sql_t,sql_w,sql_o,lmin,lmax)
        return 'SELECT %s %s FROM %s%s%s;' % (sql_s,sql_f,sql_t,sql_w,sql_o)
    def rowslice(self,rows,minimum=0,maximum=None):
        return rows

Can you help test it?

On Tuesday, 4 December 2012 15:42:16 UTC-6, Niphlod wrote:
>
> *select id, first_name, last_name, email, password, registration_key, 
> reset_password_key, registration_id from (
> select ROW_NUMBER() over (order by id) AS total_ordering,
> id, first_name, last_name, email, password, registration_key, 
> reset_password_key, registration_id
> from auth_user
> ) a
> where total_ordering
> between 1001 and 2000
> *
> is *more or less* a "limit 1000 offset 1000" (emphasis on "more or less").
>
> 1st beware: row_number() needs a "unique column" (needs something that 
> changes at every row) to calculate correctly the "total_ordering" as a 
> sequential integer. If id is not sequential is not a problem, it just has 
> to change for every row. For a table like
>
> *name email
> massimo [email protected]
> massimo [email protected]
> simone    [email protected]
> simone    [email protected]*
>
> a query like
>
> *select row_number() over (order by name) as total_ordering, name, email
> from table*
>
> would return
>
> *1 massimo [email protected] <javascript:>
> 1 massimo [email protected] <javascript:>
> 2 simone [email protected] <javascript:>
> 2 simone [email protected] <javascript:>*
>
> obviously screwing up everything ^_^ (using over(order by name, email) 
> would fix the particular case)
>
> Limiting from, e.g., a *group by* set would be a real problem using 
> row_number() for pagination (should include every column to get a distinct 
> "logical primary key")
>
> Moreover, for large datasets (or several columns in the "order by" 
> partition) is nowhere near "speedy" (internally it scans the entire 
> columns, put those in order, calculates the "row number")
>
> The order of the returned set is depending on the over(order by ) clause 
> (both the "presence" order and the "asc/desc" directives).
> *
> select * from (
> select row_number() over (order by id) total_ordering,
> * from auth_user
> ) a
> where total_ordering between 1001 and 2000
> order by id desc*
>
> returns the same set as
> *
> select * from (
> select row_number() over (order by id) total_ordering,
> * from auth_user
> ) a
> where total_ordering between 1001 and 2000
> order by id asc*
>
> it's just reverse ordered.
>
> the correct translation of "select * from auth_user order by id desc limit 
> 50 offset 50" is
> *
> select * from (
> select row_number() over (order by id desc) total_ordering,
> * from auth_user
> ) a
> where total_ordering between 51 and 100
> *
> This is "a coincidence":  a translation of "select * from auth_user order 
> by first_name limit 50 offset 50" is not possible (without resorting to 
> select top 100 * ... order by first_name and discard the first 50)
>
> BTW, MSSQL 2012 adopted the "nicer"*
> select id, first_name, last_name, email, password, registration_key, 
> reset_password_key, registration_id
> from auth_user
> offset 1000 rows
> fetch next 1000 rows only*
>
> It resolves the "syntax" problem, but its slow as hell and memory hungry 
> with large datasets
>
>

-- 



Reply via email to