读书人

保守order by和分析函数结果不一致

发布时间: 2012-09-29 10:30:01 作者: rapoo

传统order by和分析函数结果不一致
各位兄弟,以下是我遇到的问题
传统order by后用rownum=1抓数据,和用分析函数Last_Value()抓数据,发现二者结果不一致。为嘛呢?..
Last_Value()抓的数据 21C* 是对的,order by之后感觉自动忽视了部分where条件,感觉抓到SELECT PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID里order by的第一个值。

PS:传统order by的方式最内层的子查询,在部分版本的ORACLE可能识别不到T.PMDP。
我的版本可以..
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE10.2.0.1.0Production
TNS for 64-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production


SQL code
SQL> select co,pmdp,mpid from t;CO           PMDP                     MPID------------ ------------------------ ------------------------------------6            2111                     C*SQL> SELECT co,orgnlvdp,mpid,pmcen FROM txd000paa41 WHERE co='6' AND mpid='C*';CO           ORGNLVDP                 MPID------------ ------------------------ ------------------------------------PMCEN------------------------6            21                       C*21C*6            2113                     C*11C**SQL> SELECT   2   (SELECT PMCEN FROM   3    (  4      SELECT PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID    5        AND ORGNLVDP= CASE   6        WHEN ORGNLVDP=T.PMDP THEN T.PMDP   7        WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)   8        WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)   9        WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)  10        ELSE NULL END  11      ORDER BY Length(ORGNLVDP) DESC 12    ) WHERE ROWNUM=1 13   )PMCEN 14  FROM T;PMCEN------------------------11C**SQL> SELECT   2    (SELECT DISTINCT Last_Value(PMCEN) over (ORDER BY Length(ORGNLVDP) ROWS  BETWEEN unbounded preceding AND unbounded following)  3     FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID AND ORGNLVDP= CASE WHEN ORGNLVDP=T.PMDP THEN T.PMDP   4                            WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)   5                            WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)   6                            WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)   7                            ELSE NULL END  8    )pmcen   9  FROM T;PMCEN------------------------21C* --===============补充执行计划如下=================SQL> explain plan FOR   2  SELECT   3   (SELECT PMCEN FROM   4    (  5      SELECT PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID    6        AND ORGNLVDP= CASE   7        WHEN ORGNLVDP=T.PMDP THEN T.PMDP   8        WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)   9        WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)  10        WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)  11        ELSE NULL END  12      ORDER BY Length(ORGNLVDP) DESC 13    ) WHERE ROWNUM=1 14   )PMCEN 15  FROM T;已做解.SQL> SQL> select * from table(DBMS_XPLAN.Display);PLAN_TABLE_OUTPUT--------------------------------------------Plan hash value: 416088130---------------------------------------------------| Id  | Operation               | Name        | Rows  | Bytes | Cost (%CPU)| Time     |---------------------------------------------------PLAN_TABLE_OUTPUT--------------------------------------------|   0 | SELECT STATEMENT        |             |     1 |    10 |     3   (0)| 00:00:01 ||*  1 |  COUNT STOPKEY          |             |       |       |            |      ||   2 |   VIEW                  |             |    15 |   120 |     4  (25)| 00:00:01 ||*  3 |    SORT ORDER BY STOPKEY|             |    15 |   225 |     4  (25)| 00:00:01 |PLAN_TABLE_OUTPUT--------------------------------------------|   4 |     TABLE ACCESS FULL   | TXD000PAA41 |    15 |   225 |     3   (0)| 00:00:01 ||   5 |  TABLE ACCESS FULL      | T           |     1 |    10 |     3   (0)| 00:00:01 |---------------------------------------------------PLAN_TABLE_OUTPUT--------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter(ROWNUM=1)   3 - filter(ROWNUM=1)已取 18 料列.SQL> explain plan FOR   2  SELECT   3    (SELECT DISTINCT Last_Value(PMCEN) over (ORDER BY Length(ORGNLVDP) ROWS  BETWEEN unbounded preceding AND unbounded following)  4     FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID AND ORGNLVDP= CASE WHEN ORGNLVDP=T.PMDP THEN T.PMDP   5                            WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)   6                            WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)   7                            WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)   8                            ELSE NULL END  9    )pmcen  10  FROM T;已做解.SQL> SQL> SQL> select * from table(DBMS_XPLAN.Display);PLAN_TABLE_OUTPUT--------------------------------------------Plan hash value: 1796841893------------------------------------------------------------| Id  | Operation                     | Name           | Rows  | Bytes | Cost (%CPU)| Time     |------------------------------------------------------------PLAN_TABLE_OUTPUT--------------------------------------------|   0 | SELECT STATEMENT              |                |     1 |    10 |     3 (0)| 00:00:01 ||   1 |  HASH UNIQUE                  |                |     1 |    15 |     4(50)| 00:00:01 ||   2 |   WINDOW SORT                 |                |     1 |    15 |     4(50)| 00:00:01 ||   3 |    TABLE ACCESS BY INDEX ROWID| TXD000PAA41    |     1 |    15 |     2 (0)| 00:00:01 |PLAN_TABLE_OUTPUT--------------------------------------------|*  4 |     INDEX RANGE SCAN          | PK_TXD000PAA41 |     1 |       |     1 (0)| 00:00:01 ||   5 |  TABLE ACCESS FULL            | T              |     1 |    10 |     3 (0)| 00:00:01 |------------------------------------------------------------PLAN_TABLE_OUTPUT--------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   4 - access("CO"=:B1 AND "MPID"=:B2)       filter("MPID"=:B1 AND "ORGNLVDP"=CASE "ORGNLVDP" WHEN :B2 THEN :B3 WHEN              SUBSTR(:B4,1,3) THEN SUBSTR(:B5,1,3) WHEN SUBSTR(:B6,1,2) THEN SUBSTR(:B7,1,2) WHEN              SUBSTR(:B8,1,1) THEN SUBSTR(:B9,1,1) ELSE NULL END )已取 20 料列. 



[解决办法]
没看全,不过建议如下,你可以试试

SQL code
(SELECT PMCEN FROM   (    SELECT PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID        AND ORGNLVDP= CASE       WHEN ORGNLVDP=T.PMDP THEN T.PMDP       WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)       WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)       WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)       ELSE NULL END     ORDER BY Length(ORGNLVDP) DESC  ) WHERE ROWNUM=1)------------------------这句改成-------------------(SELECT PMCEN FROM   (    SELECT rownum rw, PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID        AND ORGNLVDP= CASE       WHEN ORGNLVDP=T.PMDP THEN T.PMDP       WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)       WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)       WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)       ELSE NULL END     ORDER BY Length(ORGNLVDP) DESC  ) WHERE rw=1)
[解决办法]
11 ORDER BY Length(ORGNLVDP) DESC

这里指定了 desc

last_value()那里没有指定desc阿
[解决办法]
俺的oracle还真不认识你的那个order by子查询的SQL,改写了下代码,执行的结果正常。
SELECT PMCEN FROM
(
SELECT PMCEN
FROM txd000paa41,T
WHERE txd000paa41.CO=T.CO
AND txd000paa41.MPID=T.MPID
AND ORGNLVDP= CASE
WHEN ORGNLVDP=T.PMDP THEN T.PMDP
WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)
WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)
WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)
ELSE NULL END
ORDER BY Length(ORGNLVDP) DESC
) WHERE ROWNUM=1


结果:
21C*

[解决办法]
哦,看错了,不好意思。

不过,

SQL> SELECT
2 (SELECT PMCEN FROM
3 (
4 SELECT PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID
5 AND ORGNLVDP= CASE
6 WHEN ORGNLVDP=T.PMDP THEN T.PMDP
7 WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)
8 WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)
9 WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)
10 ELSE NULL END
11 ORDER BY Length(ORGNLVDP) DESC
12 ) WHERE ROWNUM=1
13 )PMCEN
14 FROM T;

如果把where rownum=1改成 where 1=1会怎么样呢?返回几条记录?
[解决办法]
哦,看错了,不好意思。

不过,

SQL> SELECT
2 (SELECT PMCEN FROM
3 (
4 SELECT PMCEN FROM txd000paa41 WHERE CO=T.CO AND MPID=T.MPID
5 AND ORGNLVDP= CASE
6 WHEN ORGNLVDP=T.PMDP THEN T.PMDP
7 WHEN ORGNLVDP=SubStr(T.PMDP,1,3) THEN SubStr(T.PMDP,1,3)
8 WHEN ORGNLVDP=SubStr(T.PMDP,1,2) THEN SubStr(T.PMDP,1,2)
9 WHEN ORGNLVDP=SubStr(T.PMDP,1,1) THEN SubStr(T.PMDP,1,1)
10 ELSE NULL END
11 ORDER BY Length(ORGNLVDP) DESC
12 ) WHERE ROWNUM=1
13 )PMCEN
14 FROM T;

如果把where rownum=1改成 where 1=1会怎么样呢?返回几条记录?
[解决办法]
1 一般很少用last_value都用first_value() over(order by desc)

因为窗口默认限制的问题。
[解决办法]
select a,b,c from


(select t.*, row_number() over (partition by a order by b desc ) rn from t)
where rn = 1; 类似这样。。。

读书人网 >oracle

热点推荐