ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 一个复杂问题的求解过程(三)

一个复杂问题的求解过程(三)

原创 Linux操作系统 作者:yangtingkun 时间:2008-03-08 23:59:07 0 删除 编辑

今天在PUB里面看到一个帖子:http://www.itpub.net/thread-949571-1-1.html。问题本身并不复杂,不过想借这个问题简单描述一下求解的思路。

前两篇文章介绍了利用PL/SQL构造动态SQL的方法来解决问题,这里讨论如何使用SQL来实现。

一个复杂问题的求解过程(一):http://yangtingkun.itpub.net/post/468/456641

一个复杂问题的求解过程(二):http://yangtingkun.itpub.net/post/468/456695

 

 

前面两篇文章通过PL/SQL构造动态SQL的方法来实现,这是由于构造子查询的个数是不确定的。

如果利用SQL来实现,就必须首先解决这个问题。也就是说找到一个方法,在不使用多个表连接的情况下,获取所有ID不同POWER之间组合的可能性的和。

SQL> WITH T1 AS
  2  (
  3  SELECT DISTINCT T.ID, T.VALUE, LEVEL - 1 LV, T.VALUE * (LEVEL - 1) POWER
  4  FROM T
  5  CONNECT BY LEVEL <= T.POWER
  6  )
  7  SELECT * FROM T1;

        ID      VALUE         LV      POWER
---------- ---------- ---------- ----------
         2          1          1          1
         3          4          1          4
         3          4          0          0
         5          4          0          0
         1          2          2          4
         5          4          1          4
         4          5          0          0
         2          1          0          0
         1          2          0          0
         3          4          3         12
         4          5          1          5
         3          4          2          8
         1          2          1          2
         5          4          2          8

已选择14行。

现在得到的结果是展开了加权与VALUE相乘的所有可能性。下面要达到的目的是ID从1到5中,每个ID任选一条记录,并累加POWER的值,最后过滤结果为16的值。

最自然的想法就是多个表连接通过笛卡儿连接来实现,但是没有办法解决表连接数不确定的问题,想来想去,只有再次通过树形查询来实现:

SQL> SELECT ID, SYS_CONNECT_BY_PATH(POWER, ',') POWER_LIST
  2  FROM
  3  (
  4   SELECT DISTINCT T.ID, T.VALUE, LEVEL - 1 LV, T.VALUE * (LEVEL
  5   FROM T
  6   CONNECT BY LEVEL <= T.POWER
  7  )
  8  START WITH ID = 1
  9  CONNECT BY PRIOR ID + 1 = ID
 10  ORDER BY 1, 2;

        ID POWER_LIST
---------- ------------------------------
         1 ,0
         1 ,2
         1 ,4
         2 ,0,0
         2 ,0,1
         2 ,2,0
         2 ,2,1
         2 ,4,0
         2 ,4,1
         3 ,0,0,0
         3 ,0,0,12
         3 ,0,0,4
         3 ,0,0,8
         3 ,0,1,0
         3 ,0,1,12
         3 ,0,1,4
         3 ,0,1,8
         3 ,2,0,0
         3 ,2,0,12
         3 ,2,0,4
         3 ,2,0,8
         3 ,2,1,0
         3 ,2,1,12
         3 ,2,1,4
         3 ,2,1,8
         3 ,4,0,0
         3 ,4,0,12
         3 ,4,0,4
         3 ,4,0,8
         3 ,4,1,0
         3 ,4,1,12
         3 ,4,1,4
         3 ,4,1,8
         4 ,0,0,0,0
         4 ,0,0,0,5
         4 ,0,0,12,0
         4 ,0,0,12,5
         4 ,0,0,4,0
         4 ,0,0,4,5
         4 ,0,0,8,0
         4 ,0,0,8,5
         4 ,0,1,0,0
         4 ,0,1,0,5
         4 ,0,1,12,0
         4 ,0,1,12,5
         4 ,0,1,4,0
         4 ,0,1,4,5
         4 ,0,1,8,0
         4 ,0,1,8,5
         4 ,2,0,0,0
         4 ,2,0,0,5
         4 ,2,0,12,0
         4 ,2,0,12,5
         4 ,2,0,4,0
         4 ,2,0,4,5
         4 ,2,0,8,0
         4 ,2,0,8,5
         4 ,2,1,0,0
         4 ,2,1,0,5
         4 ,2,1,12,0
         4 ,2,1,12,5
         4 ,2,1,4,0
         4 ,2,1,4,5
         4 ,2,1,8,0
         4 ,2,1,8,5
         4 ,4,0,0,0
         4 ,4,0,0,5
         4 ,4,0,12,0
         4 ,4,0,12,5
         4 ,4,0,4,0
         4 ,4,0,4,5
         4 ,4,0,8,0
         4 ,4,0,8,5
         4 ,4,1,0,0
         4 ,4,1,0,5
         4 ,4,1,12,0
         4 ,4,1,12,5
         4 ,4,1,4,0
         4 ,4,1,4,5
         4 ,4,1,8,0
         4 ,4,1,8,5
         5 ,0,0,0,0,0
         5 ,0,0,0,0,4
         5 ,0,0,0,0,8
         5 ,0,0,0,5,0
         5 ,0,0,0,5,4
         5 ,0,0,0,5,8
         5 ,0,0,12,0,0
         5 ,0,0,12,0,4
         5 ,0,0,12,0,8
         5 ,0,0,12,5,0
         5 ,0,0,12,5,4
         5 ,0,0,12,5,8
         5 ,0,0,4,0,0
         5 ,0,0,4,0,4
         5 ,0,0,4,0,8
         5 ,0,0,4,5,0
         5 ,0,0,4,5,4
         5 ,0,0,4,5,8
         5 ,0,0,8,0,0
         5 ,0,0,8,0,4
         5 ,0,0,8,0,8
         5 ,0,0,8,5,0
         5 ,0,0,8,5,4
         5 ,0,0,8,5,8
         5 ,0,1,0,0,0
         5 ,0,1,0,0,4
         5 ,0,1,0,0,8
         5 ,0,1,0,5,0
         5 ,0,1,0,5,4
         5 ,0,1,0,5,8
         5 ,0,1,12,0,0
         5 ,0,1,12,0,4
         5 ,0,1,12,0,8
         5 ,0,1,12,5,0
         5 ,0,1,12,5,4
         5 ,0,1,12,5,8
         5 ,0,1,4,0,0
         5 ,0,1,4,0,4
         5 ,0,1,4,0,8
         5 ,0,1,4,5,0
         5 ,0,1,4,5,4
         5 ,0,1,4,5,8
         5 ,0,1,8,0,0
         5 ,0,1,8,0,4
         5 ,0,1,8,0,8
         5 ,0,1,8,5,0
         5 ,0,1,8,5,4
         5 ,0,1,8,5,8
         5 ,2,0,0,0,0
         5 ,2,0,0,0,4
         5 ,2,0,0,0,8
         5 ,2,0,0,5,0
         5 ,2,0,0,5,4
         5 ,2,0,0,5,8
         5 ,2,0,12,0,0
         5 ,2,0,12,0,4
         5 ,2,0,12,0,8
         5 ,2,0,12,5,0
         5 ,2,0,12,5,4
         5 ,2,0,12,5,8
         5 ,2,0,4,0,0
         5 ,2,0,4,0,4
         5 ,2,0,4,0,8
         5 ,2,0,4,5,0
         5 ,2,0,4,5,4
         5 ,2,0,4,5,8
         5 ,2,0,8,0,0
         5 ,2,0,8,0,4
         5 ,2,0,8,0,8
         5 ,2,0,8,5,0
         5 ,2,0,8,5,4
         5 ,2,0,8,5,8
         5 ,2,1,0,0,0
         5 ,2,1,0,0,4
         5 ,2,1,0,0,8
         5 ,2,1,0,5,0
         5 ,2,1,0,5,4
         5 ,2,1,0,5,8
         5 ,2,1,12,0,0
         5 ,2,1,12,0,4
         5 ,2,1,12,0,8
         5 ,2,1,12,5,0
         5 ,2,1,12,5,4
         5 ,2,1,12,5,8
         5 ,2,1,4,0,0
         5 ,2,1,4,0,4
         5 ,2,1,4,0,8
         5 ,2,1,4,5,0
         5 ,2,1,4,5,4
         5 ,2,1,4,5,8
         5 ,2,1,8,0,0
         5 ,2,1,8,0,4
         5 ,2,1,8,0,8
         5 ,2,1,8,5,0
         5 ,2,1,8,5,4
         5 ,2,1,8,5,8
         5 ,4,0,0,0,0
         5 ,4,0,0,0,4
         5 ,4,0,0,0,8
         5 ,4,0,0,5,0
         5 ,4,0,0,5,4
         5 ,4,0,0,5,8
         5 ,4,0,12,0,0
         5 ,4,0,12,0,4
         5 ,4,0,12,0,8
         5 ,4,0,12,5,0
         5 ,4,0,12,5,4
         5 ,4,0,12,5,8
         5 ,4,0,4,0,0
         5 ,4,0,4,0,4
         5 ,4,0,4,0,8
         5 ,4,0,4,5,0
         5 ,4,0,4,5,4
         5 ,4,0,4,5,8
         5 ,4,0,8,0,0
         5 ,4,0,8,0,4
         5 ,4,0,8,0,8
         5 ,4,0,8,5,0
         5 ,4,0,8,5,4
         5 ,4,0,8,5,8
         5 ,4,1,0,0,0
         5 ,4,1,0,0,4
         5 ,4,1,0,0,8
         5 ,4,1,0,5,0
         5 ,4,1,0,5,4
         5 ,4,1,0,5,8
         5 ,4,1,12,0,0
         5 ,4,1,12,0,4
         5 ,4,1,12,0,8
         5 ,4,1,12,5,0
         5 ,4,1,12,5,4
         5 ,4,1,12,5,8
         5 ,4,1,4,0,0
         5 ,4,1,4,0,4
         5 ,4,1,4,0,8
         5 ,4,1,4,5,0
         5 ,4,1,4,5,4
         5 ,4,1,4,5,8
         5 ,4,1,8,0,0
         5 ,4,1,8,0,4
         5 ,4,1,8,0,8
         5 ,4,1,8,5,0
         5 ,4,1,8,5,4
         5 ,4,1,8,5,8

已选择225行。

从上面的查询结果可以看到,ID为5的记录就等价于5个子查询的笛卡儿的结果。不过这种方式的结果合并到一个字符串里。

下面的工作就是计算每个字符串里面数值的和,然后过滤那些等于16的记录。

最终SQL实现如下:

SQL> SELECT LV_LIST
  2  FROM
  3  (
  4   SELECT ROWNUM RID,
  5    ID,
  6    SYS_CONNECT_BY_PATH(LV, ' ') LV_LIST,
  7    SYS_CONNECT_BY_PATH(POWER, ',') POWER_LIST
  8   FROM
  9   (
 10    SELECT DISTINCT T.ID, T.VALUE, LEVEL - 1 LV, T.VALUE * (LEVEL - 1) POWER
 11    FROM T
 12    CONNECT BY LEVEL <= T.POWER
 13   )
 14   START WITH ID = 1
 15   CONNECT BY PRIOR ID + 1 = ID
 16  ) A,
 17  (SELECT ROWNUM RN, COUNT(*) OVER() ID FROM T) B
 18  WHERE A.ID = B.ID
 19  GROUP BY RID, LV_LIST
 20  HAVING SUM(SUBSTR(POWER_LIST,
 21    INSTR(POWER_LIST, ',', 1, RN) + 1,
 22    INSTR(POWER_LIST || ',', ',', 1, RN + 1) - INSTR(POWER_LIST, ',', 1, RN) - 1)) = 16
 23  ;

LV_LIST
----------------------------------------------------------------------
 2 0 1 0 2
 0 0 2 0 2
 0 0 3 0 1
 2 0 2 0 1
 1 1 1 1 1
 1 1 0 1 2
 1 1 2 1 0
 2 0 3 0 0

已选择8行。

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-201785/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1964
  • 访问量
    11077414