【问题标题】:Querying database for rows until value change查询数据库中的行直到值改变
【发布时间】:2018-07-01 04:58:11
【问题描述】:

我需要执行一个查询(一个 Oracle 选择)来获取行,直到特定列的值在不知道该值的情况下发生变化

假设我们有下表:

1 - AAAA - kkkk
2 - BBBB - kkkk
3 - CCCC - kkkk
4 - DDDD - kkkk
5 - EEEE - xxxx
6 - FFFF - xxxx

专注于第三列,我只需要获取第 1、2、3、4 行(因为第 5 行和第 6 行第三列的值会发生变化)。我事先不知道 kkkk 和 xxxx 的值,所以我无法实现特定的和条件。

非常感谢

【问题讨论】:

  • 第三列是否只有 2 个可能的值?如何确定哪个是“默认”值,即最小 id?
  • 也许您应该研究一下触发该效果的因素 - docs.oracle.com/cd/B19306_01/server.102/b14200/…
  • 您好,不,我们可以为第三列设置超过 2 个值。 “默认”值是第一行,我知道如何排序查询。
  • 你如何决定顺序 - 基于第一列?是否总是以 1 开头并且具有连续的值(没有间隙)?

标签: sql oracle select


【解决方案1】:

使用分层查询:

SQL Fiddle

Oracle 11g R2 架构设置

CREATE TABLE table_name ( col1, col2 , col3 ) As
SELECT 1, 'AAAA', 'kkkk' FROM DUAL UNION ALL
SELECT 2, 'BBBB', 'kkkk' FROM DUAL UNION ALL
SELECT 3, 'CCCC', 'kkkk' FROM DUAL UNION ALL
SELECT 4, 'DDDD', 'kkkk' FROM DUAL UNION ALL
SELECT 5, 'EEEE', 'xxxx' FROM DUAL UNION ALL
SELECT 6, 'FFFF', 'xxxx' FROM DUAL;

查询 1

SELECT *
FROM   table_name
START WITH col1 = 1
CONNECT BY PRIOR col1 + 1 = col1
       AND PRIOR col3 = col3

Results

| COL1 | COL2 | COL3 |
|------|------|------|
|    1 | AAAA | kkkk |
|    2 | BBBB | kkkk |
|    3 | CCCC | kkkk |
|    4 | DDDD | kkkk |

【讨论】:

    【解决方案2】:

    使用递归 CTE 比较性能:

    with r (col1, col2, col3) as (
      select col1, col2, col3
      from your_table
      where col1 = 1
      union all
      select t.col1, t.col2, t.col3
      from r
      join your_table t on t.col1 = r.col1 + 1 and t.col3 = r.col3
    )
    select * from r
    order by col1;
    
          COL1 COL2 COL3
    ---------- ---- ----
             1 AAAA kkkk
             2 BBBB kkkk
             3 CCCC kkkk
             4 DDDD kkkk
    

    这基本上相当于@MTO 的分层查询,只是实现方式不同。正如@Boneist 所说,将它们全部分析一下,看看什么最适合您的实际情况。

    这两个假设都假设col1 值从 1 开始并且是连续的,这就是您在示例数据中显示的内容。如果不是这种情况,那么这种方法会有点复杂;但 Tabibitosan 方法无论如何都会起作用。

    【讨论】:

      【解决方案3】:

      另一种方法是使用Tabibitosan,如下所示:

      WITH your_table AS (SELECT 1 col1, 'AAAA' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 2 col1, 'BBBB' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 3 col1, 'CCCC' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 4 col1, 'DDDD' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 5 col1, 'EEEE' col2, 'xxxx' col3 FROM DUAL UNION ALL
                          SELECT 6 col1, 'FFFF' col2, 'xxxx' col3 FROM DUAL)
      SELECT col1,
             col2,
             col3
      FROM   (SELECT col1,
                     col2,
                     col3,
                     row_number() OVER (ORDER BY col1) - row_number() OVER (PARTITION BY col3 ORDER BY col1) grp
              FROM   your_table)
      WHERE  grp = 0;
      
            COL1 COL2 COL3
      ---------- ---- ----
               1 AAAA kkkk
               2 BBBB kkkk
               3 CCCC kkkk
               4 DDDD kkkk
      

      第二行与第一行不同的示例:

      WITH your_table AS (SELECT 1 col1, 'AAAA' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 2 col1, 'BBBB' col2, 'aaaa' col3 FROM DUAL UNION ALL
                          SELECT 3 col1, 'CCCC' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 4 col1, 'DDDD' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 5 col1, 'EEEE' col2, 'xxxx' col3 FROM DUAL UNION ALL
                          SELECT 6 col1, 'FFFF' col2, 'xxxx' col3 FROM DUAL)
      SELECT col1,
             col2,
             col3
      FROM   (SELECT col1,
                     col2,
                     col3,
                     row_number() OVER (ORDER BY col1) - row_number() OVER (PARTITION BY col3 ORDER BY col1) grp
              FROM   your_table)
      WHERE  grp = 0;
      
            COL1 COL2 COL3
      ---------- ---- ----
               1 AAAA kkkk
      

      我建议您测试提供给您的所有解决方案,以找出对您的数据更有效的解决方案。


      ETA:如果在您的实际数据中,您希望单独应用这些组,则只需将相关列添加到两个 row_number() 分析函数的 PARTITION BY 子句中,例如:

      WITH your_table AS (SELECT 1 id, 1 col1, 'AAAA' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 1 id, 2 col1, 'BBBB' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 1 id, 3 col1, 'CCCC' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 1 id, 4 col1, 'DDDD' col2, 'kkkk' col3 FROM DUAL UNION ALL
                          SELECT 1 id, 5 col1, 'EEEE' col2, 'xxxx' col3 FROM DUAL UNION ALL
                          SELECT 1 id, 6 col1, 'FFFF' col2, 'xxxx' col3 FROM DUAL UNION ALL
                          SELECT 2 id, 7 col1, 'GGGG' col2, 'aaaa' col3 FROM DUAL UNION ALL
                          SELECT 3 id, 8 col1, 'HHHH' col2, 'cccc' col3 FROM DUAL UNION ALL
                          SELECT 2 id, 9 col1, 'IIII' col2, 'bbbb' col3 FROM DUAL UNION ALL
                          SELECT 3 id, 10 col1, 'JJJJ' col2, 'cccc' col3 FROM DUAL UNION ALL
                          SELECT 2 id, 11 col1, 'KKKK' col2, 'aaaa' col3 FROM DUAL UNION ALL
                          SELECT 3 id, 12 col1, 'LLLL' col2, 'cccc' col3 FROM DUAL)
      SELECT id,
             col1,
             col2,
             col3
      FROM   (SELECT id,
                     col1,
                     col2,
                     col3,
                     row_number() OVER (PARTITION BY ID ORDER BY col1) - row_number() OVER (PARTITION BY id, col3 ORDER BY col1) grp
              FROM   your_table)
      WHERE  grp = 0
      ORDER BY ID, col1;
      
              ID       COL1 COL2 COL3
      ---------- ---------- ---- ----
               1          1 AAAA kkkk
               1          2 BBBB kkkk
               1          3 CCCC kkkk
               1          4 DDDD kkkk
               2          7 GGGG aaaa
               3          8 HHHH cccc
               3         10 JJJJ cccc
               3         12 LLLL cccc
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-05
        • 2012-08-02
        • 2021-12-18
        • 1970-01-01
        • 1970-01-01
        • 2012-02-23
        • 2016-02-29
        • 1970-01-01
        相关资源
        最近更新 更多