代码之家  ›  专栏  ›  技术社区  ›  aCarella

从SQL查询(Oracle)中字段的最小值获取所有行数据

  •  1
  • aCarella  · 技术社区  · 9 年前

    通过指定字段的最小值,我很难从SQL查询中获得一行所有信息。下面是我正在使用的数据和我试图获得的数据的基本示例:

    SELECT 1 AS NUM_, 'ABC' AS LET_ FROM DUAL
    UNION
    SELECT 2 AS NUM_, 'DEF' AS LET_ FROM DUAL
    UNION
    SELECT 3 AS NUM_, 'GHI' AS LET_ FROM DUAL;
    

    上述查询将产生以下结果:

    NUM_ | LET_
    -----------
      1  | ABC
      2  | DEF
      3  | GHI
    

    我只想要包含数据的行 1 ABC .这是我尝试的,如下:

    SELECT MIN(LN.NUM_) AS MIN_NUM, 
           LN.LET_ 
    FROM   (SELECT 1 AS NUM_, 'ABC' AS LET_ FROM DUAL
            UNION
            SELECT 2 AS NUM_, 'DEF' AS LET_ FROM DUAL
            UNION
            SELECT 3 AS NUM_, 'GHI' AS LET_ FROM DUAL) LN
    GROUP BY LET_;
    

    但是上面仍然给出了所有的行。我如何只在中具有最小值的行上进行归零 NUM_ 专栏,给我 1. 基础知识 ?

    3 回复  |  直到 9 年前
        1
  •  1
  •   Pரதீப்    9 年前

    您的查询找到最小值 NUM_ 每人 LET_ .得到最小值 数量_ 在所有记录中,使用 ORDER BY & ROWNUM

    SELECT LN.NUM_ AS MIN_NUM, 
           LN.LET_ 
    FROM   (SELECT 1 AS NUM_, 'ABC' AS LET_ FROM DUAL
            UNION
            SELECT 2 AS NUM_, 'DEF' AS LET_ FROM DUAL
            UNION
            SELECT 3 AS NUM_, 'GHI' AS LET_ FROM DUAL
            ORDER BY LN.NUM_) LN
    Where ROWNUM = 1
    
        2
  •  1
  •   Gordon Linoff    9 年前

    在Oracle 12C中,可以使用ANSI标准 fetch first row only 语法:

    SELECT 1 AS NUM_, 'ABC' AS LET_ FROM DUAL
    UNION ALL
    SELECT 2 AS NUM_, 'DEF' AS LET_ FROM DUAL
    UNION ALL
    SELECT 3 AS NUM_, 'GHI' AS LET_ FROM DUAL
    ORDER BY 1
    FETCH FIRST 1 ROW ONLY;
    
        3
  •  1
  •   Matthew McPeak    9 年前

    正如已经指出的,有不同的方法:

    一些方法:

    • FETCH FIRST 1 ROW ONLY
    • ORDER BY 鉴于 ROWNUM = 1
    • (我的补充) MAX KEEP
    • (我的添加)不相关子查询

    仅获取第一行 是最简单的语法,并且性能足够好。但是如果您有一个大表,其他方法也值得考虑。

    您的数据集太小,无法演示不同的性能结果,因此为了演示它们,让我们创建一个表 DBA_OBJECTS .

    create table matt_test as SELECT * FROM dba_objects;
    create unique index matt_test_u1 on matt_test (object_id);
    exec dbms_stats.gather_table_stats(USER, 'MATT_TEST');
    

    然后,尝试一些不同的方法,并使用DBMS_XPLAN进行测量:

    最大保持

    SELECT MAX (object_id) KEEP (DENSE_RANK FIRST ORDER BY object_id) object_id,
           MAX (object_name) KEEP (DENSE_RANK FIRST ORDER BY object_id) object_name
    FROM   matt_test o;
    
    ------------------------------------------------------------------------------------------
    | Id  | Operation          | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    ------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |           |      1 |        |      1 |00:00:00.29 |    8522 |
    |   1 |  SORT AGGREGATE    |           |      1 |      1 |      1 |00:00:00.29 |    8522 |
    |   2 |   TABLE ACCESS FULL| MATT_TEST |      1 |    555K|    555K|00:00:00.12 |    8522 |
    ------------------------------------------------------------------------------------------
    

    先获取(注意内存使用情况)

    SELECT object_id, object_name
    FROM   matt_test o
    order by object_id
    fetch first 1 rows only;
    
    ---------------------------------------------------------------------------------------------------------------------------
    | Id  | Operation                | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    ---------------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT         |           |      1 |        |      1 |00:00:00.33 |    8522 |       |       |          |
    |*  1 |  VIEW                    |           |      1 |      1 |      1 |00:00:00.33 |    8522 |       |       |          |
    |*  2 |   WINDOW SORT PUSHED RANK|           |      1 |    555K|      1 |00:00:00.33 |    8522 |  2048 |  2048 | 2048  (0)|
    |   3 |    TABLE ACCESS FULL     | MATT_TEST |      1 |    555K|    555K|00:00:00.12 |    8522 |       |       |          |
    ---------------------------------------------------------------------------------------------------------------------------
    

    不相关子查询

    select object_id, object_name
    from matt_test
    where object_id = ( SELECT min(object_id) FROM matt_test );
    
    -------------------------------------------------------------------------------------------------------
    | Id  | Operation                    | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    -------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT             |              |      1 |        |      1 |00:00:00.01 |       7 |
    |   1 |  TABLE ACCESS BY INDEX ROWID | MATT_TEST    |      1 |      1 |      1 |00:00:00.01 |       7 |
    |*  2 |   INDEX UNIQUE SCAN          | MATT_TEST_U1 |      1 |      1 |      1 |00:00:00.01 |       6 |
    |   3 |    SORT AGGREGATE            |              |      1 |      1 |      1 |00:00:00.01 |       3 |
    |   4 |     INDEX FULL SCAN (MIN/MAX)| MATT_TEST_U1 |      1 |      1 |      1 |00:00:00.01 |       3 |
    -------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("OBJECT_ID"=)
    

    因此,您可以看到一个不相关的子查询 可以 最大保持 方法的性能比 FETCH FIRST ROWS

    如果我写这篇文章时不考虑性能(例如,较小的数据集),默认方法是 取第一行 .