【问题标题】:Applying LIMIT and OFFSET to MS SQL server 2008 queries将 LIMIT 和 OFFSET 应用于 MS SQL Server 2008 查询
【发布时间】:2018-06-14 18:49:08
【问题描述】:

我需要将LIMITOFFSET 应用于MSSQL server 2008 中的原始查询(无需修改)。

假设原始查询是:

SELECT * FROM energy_usage

(但它可以是任意的 SELECT 查询)

到目前为止,我就是这么想的:

1. 它可以满足我的需要,但查询会生成我不需要的 extrarow_number

WITH OrderedTable AS
(
 SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS row_number,  * FROM energy_usage
)   
SELECT * FROM OrderedTable WHERE row_number BETWEEN 1 AND 10

2.这个由于某种原因不起作用并返回以下错误。

SELECT real_sql.* FROM (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS row_number, * FROM (SELECT * FROM energy_usage) as real_sql) as subquery
WHERE row_number BETWEEN 1 AND 10

比较常见的情况是:

SELECT real_sql.* FROM (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS row_number,  * FROM (real sql query) as real_sql) as subquery
WHERE row_number BETWEEN {offset} + 1 AND {limit} + {offset}

错误:

列前缀“real_sql”与表名或别名不匹配 查询中使用的名称。

【问题讨论】:

    标签: sql sql-server sql-server-2008 tsql


    【解决方案1】:

    干脆不要放在SELECT名单上:

    WITH OrderedTable AS
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS row_number,  * 
     FROM energy_usage
    )   
    SELECT col1, col2, col3 FROM OrderedTable WHERE row_number BETWEEN 1 AND 10;
    

    SELECT * 是常见的反模式,无论如何都应该避免。另外ORDER BY (SELECT 1) 不会保证执行之间的排序稳定。

    如果您只需要十行,则使用第二个:

     SELECT TOP 10 *
     FROM energy_usage
     ORDER BY ...
    

    很遗憾,你不会得到像Selecting all Columns Except One 这样好的东西

    WITH OrderedTable AS
        (
         SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS row_number,  * 
         FROM energy_usage
        )   
    SELECT * EXCEPT row_number FROM OrderedTable WHERE row_number BETWEEN 1 AND 10;
    

    【讨论】:

    • 感谢您的回答。不幸的是,我不能使用您的第一个建议,因为必须修改原始查询(原始查询是任意 SELECT 语句),我还需要传递 Offset 和 Limit(1 和 10 只是一个示例)。更新了最初的问题。
    【解决方案2】:

    这样可以解决问题。

    DECLARE @offset INT = 1;
    DECLARE @limit INT = 10;
    
    WITH Filtered AS (
        SELECT TOP (@offset + @limit) *
        FROM energy_usage
        ORDER BY 1 ASC
    ), Results AS (
        SELECT TOP (@limit) *
        FROM Filtered
        ORDER BY 1 DESC
    )
    SELECT *
    FROM Results
    ORDER BY 1 ASC;
    

    【讨论】:

    • 如果您要求的范围超出可用行数,则偏移量将无法正常工作。例如一个有 10 行且偏移量为 50 的表(不应返回任何行)。
    • @Chamika 只有当 ORDER BY 1 - 具有唯一值时,该解决方案才能正常工作。但由于原始查询是任意的,我们不能依赖它。
    猜你喜欢
    • 2012-10-26
    • 2011-03-20
    • 2013-04-03
    • 2012-08-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-20
    • 2021-05-17
    • 2020-10-02
    相关资源
    最近更新 更多