从 SQL 查询中的字段中的最小值获取所有行数据 (Oracle)
Getting all row data from minimum value in a field in a SQL query (Oracle)
我无法通过指定字段的最小值从 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
和 ABC
?
您的查询找到每个 LET_
的最小值 NUM_
。要获得所有记录中的最小值 NUM_
,请使用 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
在 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;
正如已经指出的那样,有不同的方法可以做到这一点:
一些方法:
FETCH FIRST 1 ROW ONLY
ORDER BY
然后 ROWNUM = 1
- (我的补充)
MAX KEEP
- (我的补充)不相关的子查询
FETCH FIRST 1 ROW ONLY
是最简单的语法,并且性能足够好。但如果你有一个大table,其他方法也值得考虑。
您的数据集太小,无法展示不同的性能结果,因此为了说明它们,让我们从 DBA_OBJECTS
.
中创建一个 table
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 |
------------------------------------------------------------------------------------------
FETCH FIRST(注意内存使用情况)
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"=)
因此,您可以看到不相关的子查询可以快得多,如果您可以利用索引。 MAX KEEP
方法比 FETCH FIRST ROWS
方法执行得更好,因为它使用的内存更少。
没有最好的方法:每个都有它的位置。
如果我写这篇文章时不考虑性能(例如,较小的数据集),则默认方法是 FETCH FIRST ROWS
。
我无法通过指定字段的最小值从 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
和 ABC
?
您的查询找到每个 LET_
的最小值 NUM_
。要获得所有记录中的最小值 NUM_
,请使用 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
在 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;
正如已经指出的那样,有不同的方法可以做到这一点:
一些方法:
FETCH FIRST 1 ROW ONLY
ORDER BY
然后ROWNUM = 1
- (我的补充)
MAX KEEP
- (我的补充)不相关的子查询
FETCH FIRST 1 ROW ONLY
是最简单的语法,并且性能足够好。但如果你有一个大table,其他方法也值得考虑。
您的数据集太小,无法展示不同的性能结果,因此为了说明它们,让我们从 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 |
------------------------------------------------------------------------------------------
FETCH FIRST(注意内存使用情况)
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"=)
因此,您可以看到不相关的子查询可以快得多,如果您可以利用索引。 MAX KEEP
方法比 FETCH FIRST ROWS
方法执行得更好,因为它使用的内存更少。
没有最好的方法:每个都有它的位置。
如果我写这篇文章时不考虑性能(例如,较小的数据集),则默认方法是 FETCH FIRST ROWS
。