从另一个视图 Oracle 比较一组连续的行后提取

问题描述 投票:0回答:2

嗨我想在比较来自另一个视图的行集后从视图中获取序列 ID。 我可以执行 listagg 并按序列 ID 进行分组,并将该 listagg 与其他视图匹配。但是还有其他选择吗? View 1 的 seq_id 顺序为 0,1,2,3,4.... 并且 pattern id 也是有序的。我们可以让 ROW_NUMBER()over() 有模式 id 的排序

WITH view1(seq_id, pattern_id,rnum) AS (SELECT 0 , 1 ,1 FROM dual UNION
SELECT 0 , 2,2 FROM dual UNION
SELECT 0 , 3,3 FROM dual UNION
SELECT 0 , 4,4 FROM dual UNION
SELECT 1 , 3,5 FROM dual UNION
SELECT 1 , 4,6 FROM dual UNION
SELECT 1 , 1,7 FROM dual UNION
SELECT 1 , 2,8 FROM dual UNION
SELECT 2 , 2,9 FROM dual UNION
SELECT 2 , 4,10 FROM dual UNION
SELECT 2 , 1,11 FROM dual UNION
SELECT 2 , 3,12 FROM dual )

SELECT * FROM view1 order by rnum;

例子:

查看 1

    seq id   pattern
    ------   -------
    0          1
    0          2
    0          3
    0          4
    1          3
    1          4
    1          1
    1          2
    2          2
    2          3
    2          5
    2          1

View 2 有另一列 pk_id,它是像 rownum 一样的唯一序列。始终以 1

开头
   pk_id   pattern id
  ------  ------------
    1        3
    2        4
    3        1
    4        2

View 1 的预期输出

    seq id
    ------
    1
sql oracle oracle12c relational-division
2个回答
1
投票

listagg
看起来是一个相当相关的方法。另一种方法是使用关系除法技术:

select v1.seq_id
from (
    select v1.*, 
        row_number() over(partition by seq_id order by rnum) pk_id
    from view1 v1
) v1
inner join view2 v2 
    on  v2.pattern_id = v1.pattern_id
    and v2.pk_id = v1.pk_id
group by v1.seq_id
having count(*) = (select count(*) from view2)

如果你想排除包含比参考更多模式的seq_ids,我们可以

left join
代替:

select v1.seq_id
from (
    select v1.*, 
        row_number() over(partition by seq_id order by rnum) pk_id
    from view1 v1
) v1
left join view2 v2 
    on  v2.pattern_id = v1.pattern_id
    and v2.pk_id = v1.pk_id
group by v1.seq_id
having count(*) = (select count(*) from view2)
   and count(*) = count(v2.pk_id)

1
投票

可以使用

ROW_NUMBER
解析函数对
view1
中的每个序列进行索引,然后将其与
view2
进行比较,找到匹配序列所有行的序列:

SELECT seq_id,
       MIN(rnum) AS pattern_start
FROM   ( SELECT v1.*,
                ROW_NUMBER() OVER (PARTITION BY seq_id ORDER BY rnum) AS rn,
                COUNT(*) OVER (PARTITION BY seq_id) AS num_patterns
         FROM   view1 v1
       ) v1
       INNER JOIN (
         SELECT v2.*,
                COUNT(*) OVER () AS num_patterns
         FROM   view2 v2
       ) v2
       ON     v1.rn           = v2.pk_id
          AND v1.pattern_id   = v2.pattern_id
          AND v1.num_patterns = v2.num_patterns
GROUP BY seq_id
HAVING COUNT(*) = MAX(v1.num_patterns);

其中,对于示例数据:

CREATE VIEW view1 (seq_id, pattern_id, rnum) AS
  SELECT 0, 1,  1 FROM dual UNION ALL
  SELECT 0, 2,  2 FROM dual UNION ALL
  SELECT 0, 3,  3 FROM dual UNION ALL
  SELECT 0, 4,  4 FROM dual UNION ALL
  SELECT 1, 3,  5 FROM dual UNION ALL
  SELECT 1, 4,  6 FROM dual UNION ALL
  SELECT 1, 1,  7 FROM dual UNION ALL
  SELECT 1, 2,  8 FROM dual UNION ALL
  SELECT 2, 2,  9 FROM dual UNION ALL
  SELECT 2, 4, 10 FROM dual UNION ALL
  SELECT 2, 1, 11 FROM dual UNION ALL
  SELECT 2, 3, 12 FROM dual
  ORDER BY 3;

CREATE VIEW view2 (pk_id, pattern_id) AS
  SELECT 1, 3 FROM dual UNION ALL
  SELECT 2, 4 FROM dual UNION ALL
  SELECT 3, 1 FROM dual UNION ALL
  SELECT 4, 2 FROM dual
  ORDER BY 1;

输出:

序列号 PATTERN_START
1 5

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.