选择最佳输出

时间:2016-07-24 12:17:39

标签: mysql sql oracle

这个问题与我最新的问题here .

有关

注意:这个问题在Oracle中,但解决方案也可能在MySQL中,因此您可以选择自己喜欢的解决方案。

我提出了一个查询,在我的模型之间生成层次结构依赖关系,从而产生如下输出:

FIRST_MODEL SECOND_MODEL THIRD_MODEL FOURTH_MODEL FIFTH_MODEL SIXTH_MODEL SEVENTH_MODEL EIGHTH_MODEL NINTH_MODEL
----------- ------------ ----------- ------------ ----------- ----------- ------------- ------------ -----------
test1       test                                                                                                 
test2       test
test2       test6                                                                                                 
test3       test                                                                                                 
test3       test2                                                                                                
test3       test2        test     
test3       test2        test6                                                                                    
test4       test3                                                                                                
test4       test3        test                                                                                    
test4       test3        test2                                                                                   
test4       test3        test2       test   
test4       test3        test2       test6 
.....      

ETC ..,这意味着FIRST_MODEL等待SECOND_MODEL等等。

问题是我必须从这里选择最完成输出,这基本上只意味着"离开"并且只有"离开"如果填充了大部分数据,将会提供一些数据示例。这是一个虚拟的例子:

First | Second | Third | Forth | Fifth ....
 1       2        null    null    null
 1       2        6       null    null
 1       2        5       null    null
 1       2        5       7       null
 1       3        null    null    null
 1       4        6       null

结果应为

First | Second | Third | Forth | Fifth ....
 1       2        6       null    null
 1       2        5       7       null
 1       4        6       null    null

其他所有内容都被排除在外,因为它们是所选输出的一部分。

因此使用ROW_NUMBER()或其他内容的查询将无效,

SELECT t.*,
       ROW_NUMBER() OVER(PARTITION BY ????? ORDER BY ???
FROM <Another Query>

我不知道如何通过一组未知的列进行分区。

E.G。这里的输出应该是:

test4       test3        test2       test   
test4       test3        test2       test6   

因为其他一切,只是这两个结果的一部分。我真的坚持这个,我不知道我可以使用哪个窗口功能,因为每个组每次都会更改,层次结构的级别是未知的,可以更改。

我更喜欢避免使用动态SQL,我知道可以使用过程来完成,我也知道如何构建一个,但我有一个要求避免它。

我还提供了创建使用分层查询在Oracle中构建的数据的查询,也许有人会想到从一开始就只获取最完整的行:

SELECT distinct REGEXP_SUBSTR( tests, '[^|]+', 1, 1 ) AS first_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 2 ) AS second_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 3 ) AS third_model,
       ......
FROM   (
  SELECT SYS_CONNECT_BY_PATH( wait_4_model_name, '|' ) || '|' ||  grand_model AS tests
  FROM  (SELECT * FROM Tab_Name)
  CONNECT BY NOCYCLE PRIOR grand_model = wait_4_model_name
)

有关数据的更多信息,您可以在上面的链接中输入我的上一个问题。

提前致谢。

3 个答案:

答案 0 :(得分:1)

我终于找到了使用LAG()ROW_NUMBER()的解决方案,通过对所有列排序内部查询的结果,我在记录之前得到更多填充记录只有部分被填充,然后,LAG()我检查所有列的串联是否在最后一条记录的串联内,如果是 - 过滤它。

E.G。

FIRST | SECOND | THIRD | FORTH ... | RNK | IND_TO_EXCLUDE
  1        2       3       null       1        0
  1        2       4       null       2        0
  1        2       null    null       3        1
  2        3       5       null       4        0 
  ............

Rnk = 3将得到ind 1,因为所有列(12)的串联都在最后一个记录列(123)的串联内。

SELECT first_model,second_model,third_model,fourth_model,fifth_model,sixth_model,seventh_model,eighth_model,ninth_model
FROM (       
SELECT first_model,second_model,third_model,fourth_model,fifth_model,sixth_model,seventh_model,eighth_model,ninth_model,
       CASE
         WHEN INSTR(LAG(t.all_level, 1) OVER(ORDER BY t.rnk), t.all_level) > 0 THEN
          1
         ELSE
          0
       END as ind_to_exclude
  FROM (SELECT s.*,
               ROW_NUMBER() OVER(ORDER BY first_model, second_model, third_model, fourth_model, fifth_model, sixth_model, seventh_model, eighth_model, ninth_model) as rnk,
               NVL(s.first_model, '') || NVL(s.second_model, '') ||
               NVL(s.third_model, '') || NVL(s.fourth_model, '') ||
               NVL(s.fifth_model, '') || NVL(s.sixth_model, '') ||
               NVL(s.seventh_model, '') || NVL(s.eighth_model, '') ||
               NVL(s.ninth_model, '') as all_level
          FROM (SELECT distinct REGEXP_SUBSTR(tests, '[^|]+', 1, 1) AS first_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 2) AS second_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 3) AS third_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 4) AS fourth_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 5) AS fifth_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 6) AS sixth_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 7) AS seventh_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 8) AS eighth_model,
                            REGEXP_SUBSTR(tests, '[^|]+', 1, 9) AS ninth_model
              FROM (SELECT SYS_CONNECT_BY_PATH(wait_4_model_name, '|') || '|' ||
                           grand_model AS tests
                      FROM (SELECT *
                              FROM DEL_SAGI_FOR_HIERARCHY
                             WHERE grand_model NOT IN ('Dwh_0_Start_Flow','Dwh_99_End_Flow','create_flag_4_runing')
                               AND wait_4_model_name NOT IN ('Dwh_0_Start_Flow','Dwh_99_End_Flow','create_flag_4_runing')
                               AND co_dependent = 0)
                        CONNECT BY NOCYCLE
                         PRIOR grand_model = wait_4_model_name)) s
                         ) t
                )  tt
WHERE tt.ind_to_exclude = 0 

答案 1 :(得分:0)

如果您想要最多级别,您可以按顺序获取它们:

with t as (<your query here>)
select t.*
from t
order by ((case when first_model is not null then 1 else 0 end) +
          (case when second_model is not null then 1 else 0 end) +
          . . .
         ) desc;

您可以使用fetch first 1 row only(Oracle 12c +)或使用子查询选择最上面的一个。

或者,您可以保留完整的tests字符串,并计算其中|的数量:

order by regexp_count(tests, '[|]') desc

您可以使用row_number()执行类似操作:

with . . .
select
from (select t.*,
             row_number() over (partition by <group> order by regexp_count(tests, '[|]') desc) as seqnum
      from t
     ) t
where seqnum = 1;

从问题中如何定义群组尚不清楚。

答案 2 :(得分:0)

Oracle安装程序

CREATE TABLE table_name ( GRAND_MODEL, WAIT_4_MODEL_NAME ) AS
SELECT 'test',  'test1' FROM DUAL UNION ALL
SELECT 'test',  'test2' FROM DUAL UNION ALL
SELECT 'test',  'test3' FROM DUAL UNION ALL
SELECT 'test2', 'test3' FROM DUAL UNION ALL
SELECT 'test3', 'test4' FROM DUAL UNION ALL
SELECT 'test4', 'test5' FROM DUAL;

<强>查询

SELECT REGEXP_SUBSTR( tests, '[^|]+', 1, 1 ) AS first_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 2 ) AS second_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 3 ) AS third_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 4 ) AS fourth_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 5 ) AS fifth_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 6 ) AS sixth_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 7 ) AS seventh_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 8 ) AS eighth_model,
       REGEXP_SUBSTR( tests, '[^|]+', 1, 9 ) AS ninth_model
FROM   (
  SELECT SYS_CONNECT_BY_PATH( wait_4_model_name, '|' ) || '|' ||  grand_model AS tests
  FROM  table_name
  WHERE CONNECT_BY_ISLEAF = 1
  START WITH wait_4_model_name NOT IN ( SELECT grand_model FROM table_name )
  CONNECT BY PRIOR grand_model = wait_4_model_name
);

<强>输出

FIRST_MODEL SECOND_MODEL THIRD_MODEL FOURTH_MODEL FIFTH_MODEL SIXTH_MODEL SEVENTH_MODEL EIGHTH_MODEL NINTH_MODEL
----------- ------------ ----------- ------------ ----------- ----------- ------------- ------------ -----------
test1       test                                                                                                 
test5       test4        test3       test                                                                        
test5       test4        test3       test2        test