`
zhouchaofei2010
  • 浏览: 1106943 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

诡异的fetch first n rows only !!

阅读更多

诡异的fetch first n rows only  !!

 

前天解决了系统一个历史科目分页查询的bug,虽然当时解决了,但并不知道造成bug的具体原因。于是,这两天通过查资料和测试终于知道了bug产生的原因

 

 

bug描述:系统在分页查询的时候,从第2页开始,以后的每一页数据都和第2页数据相同的,正确的情况应该是每页都不相同的

 

数据描述:历史科目表中的数据每天都会有数据生成,生成数据的时候会专门给数据指定一个排序号,放入列sortNum中。所以在同一天内排序号都是不同的,但是天与天之间,对应同一个科目号的排序号sortNum有大量的重复

 

                            

原始有bug的sql如下:                                          

                                          

select * from (                                 

select tba.*, ROW_NUMBER() OVER() AS ROWNUM from

(                                                                                         

  select * from 历史科目表 where 1=1             

  and glcode = '3801'                                                                  

  order by  sortNum                                                                       

) tba fetch first 50 rows only                

) where ROWNUM >40 and ROWNUM <=50    

 

 

当时解决的办法,是在子查询的order by后面多添加了日期acdate,结果正确了

 

select * from (                                 

select tba.*, ROW_NUMBER() OVER() AS ROWNUM from

(                                                                                         

  select * from 历史科目表 where 1=1             

  and glcode = '3801'                                                                  

  order by  sortNum ,acdate                                                                      

) tba fetch first 50 rows only                

) where ROWNUM >40 and ROWNUM <=50    

 

可是面对如此奇怪的问题,到底出现了在哪呢?

 

经过实验发现,如下2个对sql的改动都能使结果正确

 

1、把order by  sortNum 子句在 放入 OVER()函数中,如下

select * from (                                 

select tba.*, ROW_NUMBER() OVER(order by  sortNum ) AS ROWNUM from

(                                                                                         

  select * from 历史科目表 where 1=1             

  and glcode = '3801'                                                                  

  order by  sortNum                                                                     

) tba fetch first 50 rows only                

) where ROWNUM >40 and ROWNUM <=50  

 

 

2、把 fetch first 50 rows only 的语句去掉

 

select * from (                                 

select tba.*, ROW_NUMBER() OVER() AS ROWNUM from

(                                                                                         

  select * from 历史科目表 where 1=1             

  and glcode = '3801'                                                                  

  order by  sortNum                                                                     

) tba                

) where ROWNUM >40 and ROWNUM <=50  

 

 

怀疑是fetch first n rows only这条语句搞的鬼,于是进行了如下的数据比对

 

把 select * from 历史科目表 where 1=1 and glcode = '3801' order by sortNum 查询结果前10条记录复制日期列到UtraEdit中

 

和把select * from 历史科目表 where 1=1 and glcode = '3801' order by sortNum fetch first 10 rows only查询结果的日期列也复制到UtraEdit中,在UtraEdit的列模式下进行比对

 

 

发现10条数据是一样的,但排序不一样了,后来把测试范围扩大到20,30,40,50条,发现一个规律,加不加fetch first n rows only最后取得的结果记录都是一样的,但是加了fetch first n rows only后,会对原来order by 相同列的记录的换了一种方式排序。原来order by如果列有相同值就按物理顺序排的(即先插入的数据排在前面),但是 加了fetch first n rows only 后竟然改变了对查询结果的排序方式,在ordery by 字段值相同的时候,90% 以上的数据是按键值(这里是日期acdate)倒序排序的。所以按照

 

select * from (                                 

select tba.*, ROW_NUMBER() OVER() AS ROWNUM from

(                                                                                         

  select * from 历史科目表 where 1=1             

  and glcode = '3801'                                                                  

  order by  sortNum                                                                       

) tba fetch first 50 rows only                

) where ROWNUM >40 and ROWNUM <=50  

 

查出的结果,如果sortNum都相同的话,永远取到日期acdate 最小的那10条数据,所以分页查询的时候,就表现为点后面几页的按钮,显示的结果都是一样的状况

 

 

原来如此! 诡异的fetch first n rows only  !! 但不知道这是db2的故意优化呢,还是DB2的bug,其他的数据库oracle、sqlserver也会是这样吗的,没有环境这里就暂时先不测试了。如果有网友能有这方面的测试数据,分享一下,那就太感激了!!

 

周末愉快~ ^-^ 

2
3
分享到:
评论

相关推荐

    查询前几条记录

    例如,在PostgreSQL中,可以使用`FETCH FIRST N ROWS ONLY`或`OFFSET M ROWS FETCH NEXT N ROWS ONLY`: ```sql SELECT * FROM 表名 FETCH FIRST N ROWS ONLY; SELECT * FROM 表名 OFFSET M ROWS FETCH NEXT N ROWS...

    sql语句查询指定的条数

    - `FETCH FIRST n ROWS ONLY`语法可以看作是`LIMIT`的一个变体,用于限制返回的记录数。 - 这个语法同样支持与`ORDER BY`子句结合使用。 ### 总结 以上介绍了在Oracle、MySQL、SQL Server和DB2四种数据库系统中...

    DB2编程序技巧

    你可以使用`FETCH FIRST n ROWS ONLY`来获取数据表中的前n条记录,例如`SELECT * FROM tb_market_code FETCH FIRST 1 ROWS ONLY`。然而,这种语法不支持直接将结果集赋值给变量,如`SELECT market_code INTO v_...

    Oracle 的top问题

    此外,值得注意的是,Oracle 12c引入了一种新的分页查询方式——`FETCH FIRST n ROWS ONLY`,这使得处理"Top N"问题变得更加直观和高效: ```sql SELECT * FROM emp ORDER BY sal DESC FETCH FIRST 3 ROWS ONLY; ``...

    DB2编程基础DB2编程基础DB2编程基础

    - 要选取数据表中的第一条记录,可以使用 `FETCH FIRST N ROWS ONLY` 子句。例如:`SELECT * FROM tb_market_code FETCH FIRST 1 ROWS ONLY`。然而,将记录直接赋值给变量则需要使用游标,如下所示: ```sql ...

    oracle分页代码

    此外,Oracle 12c及以上版本引入了新的CTE(公共表表达式)特性,提供了更简洁的分页查询方式——`FETCH FIRST n ROWS ONLY`和`OFFSET m ROWS`: ```sql SELECT column1, column2, ... FROM your_table WHERE your_...

    Oracle的SQL分页实践

    另外,Oracle 12c引入了一种名为"物理行限制"的新特性,即`FETCH FIRST n ROWS ONLY`,这使得分页查询更加简洁: ```sql SELECT * FROM your_table ORDER BY some_column FETCH FIRST 10 ROWS ONLY; ``` 在Java...

    Oracle和DB2的转换[参照].pdf

    - DB2提供了`fetch first N rows only`来达到相同的效果,如:`Select * from TableName fetch first N rows only;` 2. **获取系统日期** - Oracle中获取当前日期的命令是`Select sysdate from dual;` - 在DB2中...

    Oracle分页(limit方式的运用)

    FETCH FIRST 10 ROWS ONLY; ``` 这里的`page_number`代表当前页码,例如当`page_number=2`时,查询第2页的数据,即从第11条到第20条记录。 #### 三、Oracle分页的实现步骤 1. **确定分页参数**:首先需要确定每页...

    Oracle和跨页选择(新手)

    除了ROWNUM,Oracle 12c引入了新的SQL语法`FETCH FIRST n ROWS ONLY`,这让分页查询变得更加简洁: ```sql SELECT * FROM table ORDER BY some_column OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; ``` 这种语法更加...

    oracle分页,比较简单很好懂

    虽然`LIMIT`不是Oracle的原生语法,但Oracle 12c引入了`FETCH FIRST n ROWS ONLY`和`OFFSET m ROWS`来实现类似的功能。这两个子句可以组合使用,用于获取结果集的特定部分。例如,如果我们想获取第11到20条记录,...

    oracle一条sql语句分页

    一种改进的方法是使用`FETCH FIRST n ROWS ONLY`(仅在Oracle 12c及更高版本中可用),这可以显著减少查询时间。 ```sql SELECT * FROM ( SELECT * FROM tables ) WHERE ROWNUM FETCH FIRST endNum ROWS ...

    oracle和db2的区别

    - `FETCH FIRST N ROWS ONLY`是一个明确且直观的方法来限制返回的行数。 #### 2. 获取系统日期 - **Oracle**: - 使用`SELECT SYSDATE FROM DUAL;` - `SYSDATE`是一个预定义的伪列,返回当前系统的日期和时间。 ...

    Oracle中ROWNUM的使用技巧.docx

    5. **其他方法**:除了ROWNUM,还可以考虑使用Oracle的其他高级查询功能,如`FETCH FIRST N ROWS ONLY`(需要Oracle 12c及以上版本),它可以直接用于实现分页,同时保持排序的正确性。 总之,ROWNUM在Oracle中是一...

    DB2 优化,db2性能优化,查询优化

    此外,如果希望快速获取前几行数据但对后续行的延迟不太敏感,可以结合使用`FETCH FIRST n ROWS ONLY`。 - 示例代码:`SELECT EMPNAME, SALARY FROM EMPLOYEE ORDER BY SALARY DESC FETCH FIRST 100 ROWS ONLY ...

    各数据库分页语法支持

    DB2 支持两种分页方法:使用 ROW_NUMBER() 函数和 FETCH FIRST ROWS ONLY 语法。 1. **ROW_NUMBER() 函数分页**: ```sql SELECT * FROM ( SELECT sid, ROW_NUMBER() OVER (ORDER BY sid) AS ROWNUM FROM test...

    DB2使用经验积累

    例如,`SELECT * FROM table LIMIT n` 或 `SELECT * FROM table FETCH FIRST n ROWS ONLY`。 此外,DB2还涉及很多其他关键领域,如性能调优、安全性、备份恢复、并发控制等。理解并掌握这些概念和技巧对于有效地...

    ORACLE分页查询SQL语法

    另外,Oracle 12c引入了新的分页查询方式——`FETCH FIRST n ROWS ONLY` 和 `OFFSET m ROWS`,这提供了更直观且高效的分页方式,可以替代上述的ROWNUM方法。例如: ```sql SELECT * FROM k_task WHERE Flight_date...

    Oracle SQL语句分页问题

    从Oracle 12c开始,引入了新的语法`FETCH FIRST n ROWS ONLY`,可以直接用来限制返回的行数,这为分页提供了更加简洁的方式。 **示例代码**: ```sql WITH CTE AS ( SELECT * FROM table_name ORDER BY column_...

Global site tag (gtag.js) - Google Analytics