hnweicr 发表于 2010-11-18 12:40

已解决:请教 :上下记录有逻辑关系的数据如何按顺序排序(10G)

本帖最后由 hnweicr 于 2010-11-19 20:28 编辑

比如 字段为 AB C三者之间的关系是: C=A+B
而且 上一记录的C 等于下一记录的A
我想按这种逻辑关系把数据进行排序,发现很难。
用connect byprior也试不出来,请各位帮忙下

create table prior_test (a number(4),b number(4),c number(4));

insert into prior_test values(110,-110,0);
insert into prior_test values(100,-100,0);
insert into prior_test values(0,110,110);
insert into prior_test values(0,100,100);
commit;

已知道这四条记录之前的记录 为    5   -5       0
已知道这四条记录之后的记录为   0    10000 10000

希望得出这样的顺序

5      -5                      0
0      100                   100
100    -100                  0
0      110                   110
110    -110                   0
0      10000                10000
或者是
5      -5                      0
0      110               110
110    -110                  0
0      100                   100
100    -100                   0
0      10000                10000

均可.

xhw060303 发表于 2010-11-18 14:39

:em27:

hnweicr 发表于 2010-11-18 18:21

看来要用递归算法或是穷举算法写个过程或函数才行。
有熟悉oracle递归的朋友能否帮忙写一个。

hnweicr 发表于 2010-11-19 20:26

本帖最后由 hnweicr 于 2010-11-20 00:12 编辑

回复 1# hnweicr

今天有空,研究了一下oracleselect * from tab connect by prior start with的用法,发现怎么用都得不到我想要的,
也许是我自己笨,搞不掂而已。不熟oracle的递归算法,于是用穷举,有点傻但至少能解决问题。(还没优化,可能有bug)
希望其他朋友能有更好的方法。DECLARE
      -----在此只考虑处理表中的数据,也就是说,不考虑表中数据 之前记录的C 及之后记录的A
      -----我只是算表中的数据头尾相连起来应有的几套方案。只要再把之前的C及之后的A传进来即可得到想要的方案(可能是多套)
      -----代码只考虑一个用户在同一时间有少于10笔的情况超过10笔的情况尚需再改
      CURSOR get_all IS
      SELECT abalance, c as my_left
      FROM prior_test
      ;
      ------------------------------------------------------------------
      TYPE user_record IS RECORD
      (   seq   NUMBER(10),
          balance NUMBER(13,3),
          my_left NUMBER(13,3)
      );
   TYPE user_array ISTABLE OF user_record
   INDEX BY BINARY_INTEGER;
   ------------------------------------------------------------------
   record_array user_array; --表中数据数组
   test_array   user_array; --组合数据测试数组
   vn_INDEX NUMBER(3):=0;
   vn_start NUMBER(18):=0;--排列起点数
   vn_end   NUMBER(18):=0;--排列终点
   vn_count NUMBER(18):=0;
   vn_number NUMBER(1):=0;
   test_ok   NUMBER(10):=0;
BEGIN
      FOR i IN get_all
      LOOP
          vn_INDEX:=vn_INDEX+1;
          record_array(vn_INDEX).seq:=vn_INDEX;
          record_array(vn_INDEX).balance:=i.balance;
          record_array(vn_INDEX).my_left:=i.my_left;
      END LOOP;
      FOR i IN1..record_array.COUNT
      LOOP
          vn_start:=vn_start+i*power(10,(record_array.COUNT-i));--比如6行数的话就是123456
      END LOOP;
      ------------------------------------------------------------------
      FOR i INREVERSE 1..record_array.count ---654321
      LOOP
          vn_end:=vn_end+i*power(10,(i-1));
      END LOOP;
      FOR i IN vn_start..vn_end
      LOOP--主要是取得所有数据排列有多少种可能 ,数据中含有123456各位数且不重复的均符合
          vn_count:=0;
          FOR j INREVERSE 1..record_array.COUNT
          LOOP
            vn_number:=0;
            vn_number:=TO_NUMBER(SUBSTR(TO_CHAR(i),j,1));
            IF   ( vn_number=0 OR vn_number>record_array.COUNT OR instr(TO_CHAR(i),TO_CHAR(vn_number),1,2)>0) THEN
               EXIT;
            END IF;
            vn_count:=vn_count+1;
          END LOOP;
          IF vn_count=record_array.COUNT THEN
             FOR j IN 1..record_array.COUNT
             LOOP
               test_array(j):=record_array(TO_NUMBER(SUBSTR(TO_CHAR(i),j,1)));
             END LOOP;
             ------------------------------------------------------------------
             test_ok:=0;   --排列顺序数据是否符合逻辑关系
             FOR j IN 1..record_array.COUNT-1
             LOOP
               IF (test_array(TO_NUMBER(j)).my_left<>test_array(TO_NUMBER(j)+1).balance) THEN
                  EXIT;
               END IF;
               test_ok:=test_ok+1;
             END LOOP;
             IFtest_ok=record_array.COUNT-1 THEN--符合逻辑
                DBMS_OUTPUT.PUT_LINE(TO_CHAR(i));
               FOR j IN 1..record_array.COUNT
               LOOP
                  DBMS_OUTPUT.PUT_LINE (TO_CHAR(test_array(TO_NUMBER(j)).seq)||'***'||TO_CHAR(test_array(TO_NUMBER(j)).balance)||
                               '***'||TO_CHAR(test_array(TO_NUMBER(j)).my_left));
               END LOOP;
             END IF;
          END IF;
      END LOOP;
END;

renxiao2003 发表于 2010-11-19 21:27

回复 4# hnweicr


    看来想用SQL语句实现比较难。

luanhemenghu 发表于 2012-01-14 09:21

使用触发器,可以解决
页: [1]
查看完整版本: 已解决:请教 :上下记录有逻辑关系的数据如何按顺序排序(10G)