2016-02-19 69 views
1

编写一个查询与循环如何编写循环执行以下任务的查询: (代个人成绩的ID)如何在Oracle

SELECT * From Table where id= 24 
    Id | next_to_check | next_to_check_2 
    24| 34,23  | 4 

然后我们检查了我们显示的手段34, 23.4

SELECT * From tablle where id = 34 
    SELECT * From tablle where id = 23 
    SELECT * From tablle where id = 4 

则替换结果34,23,4然后与结果的结果,并越陷越深

24-> 34,23,4 
34-> which results in a 
23-> which results in a 
4-> is as a result of 

什么结果 - >结果,结果等......

,当我做手工,它看起来像这样:

enter image description here

+0

你可以请张贴一些更多的细节?了解表格的确切结构,您的数据和预期结果的示例会很有用 – Aleksej

+6

您的表格似乎设计得非常糟糕。你在'next_to_check'中有一个复合数据元素,显然,'next_to_check'和'next_to_check2'是存储相同值的不同列。如果将此模型化为标准的父子层次结构表,它会更有意义(并使查询更容易编写)。 –

+0

他们的方式我看到它有两个问题:1您需要将多个值拆分为不同的行。其次你需要遍历一个层次结构。你可以使用[table(cast(multiset(](http://stackoverflow.com/questions/14328621/splitting-string-into-multiple-rows-in-oracle)将其分成多行,然后使用[递归CTE](http:// stackoverflow。com/questions/4659803 /递归在oracle中),或者[[通过事先连接]](https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries003.htm)遍历层次结构 – xQbert

回答

0

的查询是,如果一个表很简单已经适当地正常化了。
正如在评论中提到,有两个问题:

  • next_to_checknext_to_check2是存储相同的值
  • 两列包含逗号分隔值列表两列,而不是单个值

表应该是这样的:

SELECT * From Table where id= 24 
    Id | next_to_check | 
    24| 34   | 
    24| 23   | 
    24| 4   | 

其中一个next_to_check列的类型必须与id列相同,以避免不必要的转换。

对于上述表的查询可能只是:

SELECT * 
FROM "TABLE" 
start with id = 24 
connect by id = prior next_to_check; 

如果该表不能正常化,那么你就可以“飞”使用这样的查询数据标准化

WITH normalized_data As (
    SELECT id, trim(regexp_substr(next_to_check, '[^,]+', 1, LEVEL)) next_to_check 
    FROM "TABLE" 
    CONNECT BY LEVEL <= regexp_count(next_to_check, ',')+1 
    UNION ALL 
    SELECT id, trim(regexp_substr(next_to_check_2, '[^,]+', 1, LEVEL)) next_to_check 
    FROM "TABLE" 
    CONNECT BY LEVEL <= regexp_count(next_to_check_2, ',')+1 
) 
SELECT * FROM normalized_data 

再粘上第一查询上述查询:

WITH normalized_data As (
    SELECT id, trim(regexp_substr(next_to_check, '[^,]+', 1, LEVEL)) next_to_check 
    FROM "TABLE" 
    CONNECT BY LEVEL <= regexp_count(next_to_check, ',')+1 
    UNION ALL 
    SELECT id, trim(regexp_substr(next_to_check_2, '[^,]+', 1, LEVEL)) next_to_check 
    FROM "TABLE" 
    CONNECT BY LEVEL <= regexp_count(next_to_check_2, ',')+1 
) 
SELECT * FROM normalized_data 
start with id = 24 
connect by id = prior next_to_check; 

但是这种“解决方法”的表现会很差,它可能适用于100或1000条记录,但在更大的表上需要数年。

+0

考虑以处理NULL列表元素使用该REGEXP_SUBSTR()调用应该发生:'REGEXP_SUBSTR(next_to_check, '(*)(,| $)?',1,LEVEL,NULL,1)'。看到这个更多的信息,正如使用正则表达式''[^,] +''解析一个带NULL元素的列表会让你陷入麻烦:https://stackoverflow.com/questions/31464275/split-comma-separated-values -to-列,在甲骨文/ 31464699#31464699。当然,这可能并不适用于这种确切的情况,但您最好意识到这个问题,以免在不知情的情况下返回不正确的数据! –