ROW_NUMBER()没有正确排序记录

时间:2012-01-04 07:42:56

标签: java sql oracle row-number

我不得不将数据从oracle表复制到文件中。

我有一个连接查询,它获取800k记录,所以我使用row_number()函数和order by子句生成4个文件,每个包含200k。

查询:

SELECT * FROM (
    SELECT  ROW_NUMBER() OVER ( order by FILE_KEY desc ) rn,
        FILE_KEY, ROUTING_NO, INTLROUT_TYPE, ABBR_COUNTRY_CODE_2D, HO_CATALOG_NO 
    FROM BANK_INTL_ROUT_TBL rout, BANK_INTL_LOC_TBL loc 
    WHERE loc.CATALOG_NO = rout.FILE_KEY) 
WHERE rn BETWEEN start AND end;

参数:

For 1st File  : start =1 ,end = 200000
For 2nd File  : start =200001 ,end = 400000
For 3rd File  : start =400001 ,end = 600000
For 4th File  : start =600001 ,end = 800000

但是当我在sql查询浏览器中使用此查询检查最后10行并且最后10行文件不同时,文件和SQL查询浏览器中的序列是不同的。

SELECT * FROM (
    SELECT  ROW_NUMBER() OVER(  order by FILE_KEY desc ) rn,
        FILE_KEY,ROUTING_NO,INTLROUT_TYPE,ABBR_COUNTRY_CODE_2D,HO_CATALOG_NO 
    FROM BANK_INTL_ROUT_TBL rout, BANK_INTL_LOC_TBL loc 
    WHERE loc.CATALOG_NO=rout.FILE_KEY) 
WHERE rn BETWEEN 709990 AND 80000;

3 个答案:

答案 0 :(得分:1)

这可能是因为你有这样的东西

row_number file_key 
799998     same_number
799999     same_number
800000     same_number
800001     same_number
800002     same_number
800003     same_number
800004     same_number

因为您按file_key订购。

您如何观察到不同的数据?从你的其他专栏。所以,你可以使用:

SELECT  ROW_NUMBER() OVER(order by FILE_KEY desc, ROUTING_NO, INTLROUT_TYPE, ABBR_COUNTRY_CODE_2D, HO_CATALOG_NO ) rn

或(第二个原因),您的基本表在您的查询之间发生了变化。

UDPDATE :您可以使用use_hash提示来加快查询速度。 5小时对于此查询来说太多了。

SELECT * FROM (
    SELECT  /*+use_hash(rout loc)*/
        ROW_NUMBER() OVER(order by FILE_KEY desc, ROUTING_NO, INTLROUT_TYPE, ABBR_COUNTRY_CODE_2D, HO_CATALOG_NO ) rn,
        FILE_KEY, ROUTING_NO, INTLROUT_TYPE, ABBR_COUNTRY_CODE_2D, HO_CATALOG_NO 
    FROM BANK_INTL_ROUT_TBL rout, BANK_INTL_LOC_TBL loc 
    WHERE loc.CATALOG_NO = rout.FILE_KEY) 
WHERE rn BETWEEN start AND end;

答案 1 :(得分:1)

在over子句中,按BANK_INTL_LOC_TBL中的唯一字段排序:

SELECT * FROM (
    SELECT  ROW_NUMBER() OVER ( order by loc.**LOC_KEY** desc ) rn,
        FILE_KEY, ROUTING_NO, INTLROUT_TYPE, ABBR_COUNTRY_CODE_2D, HO_CATALOG_NO 
    FROM BANK_INTL_ROUT_TBL rout, BANK_INTL_LOC_TBL loc 
    WHERE loc.CATALOG_NO = rout.FILE_KEY) 
WHERE rn BETWEEN start AND end
ORDER BY rn;

更新:根据@Shannon Severance评论 添加order by子句

答案 2 :(得分:0)

如果您的Oracle安装有备用磁盘(您应该这样做!),那么它可能会更快地执行以下操作而不是运行内部查询4次

CREATE TABLE bank_data
NOLOGGING
PARALLEL 4
AS SELECT  ROW_NUMBER() OVER ( order by FILE_KEY desc ) rn,
    FILE_KEY, ROUTING_NO, INTLROUT_TYPE, ABBR_COUNTRY_CODE_2D, HO_CATALOG_NO 
FROM BANK_INTL_ROUT_TBL rout, BANK_INTL_LOC_TBL loc 
WHERE loc.CATALOG_NO = rout.FILE_KEY);

要使用的并行数量(我的示例中的数字4)将取决于数据库可以处理的并发工作量,主要取决于CPU的数量。

在完成之后,(这应该花费不到5个小时!)然后你可以在bank_dump表上运行简单的选择来拉出你想要的记录

SELECT *
FROM bank_dump
where rn < 200000
例如,

用于您的第一个数据集。