MAX SQL-запрос в оракуле - PullRequest
       18

MAX SQL-запрос в оракуле

0 голосов
/ 04 июня 2011

У меня таблица testmax выглядит следующим образом:

I                      J                      
---------------------- ---------------------- 
1                      2                      
2                      4                      
3                      3       

Теперь проблема в том, как мне найти I с максимальным J, следуя которому я могу найти только то, что является максимальным J

SELECT MAX(j) 
  FROM testmax

но после этого я получаю эту ошибку: ORA-00937: not a single-group group function:

SELECT i, MAX(j) 
  FROM testmax

Ответы [ 5 ]

4 голосов
/ 04 июня 2011

Обратите внимание, что ваш вопрос все еще несколько двусмысленен;что должно быть возвращено, если существует более одной записи с максимальным значением для J. Вернете ли вы одну запись или несколько?Мой ответ применим только в том случае, если вы хотите, чтобы одна запись была возвращена.

И в этом случае приведенный ниже запрос, использующий агрегатную функцию FIRST / LAST для i, является наиболее эффективным запросом.протестируйте с вашей таблицей:

SQL> create table testmax (i,j)
  2  as
  3  select 1, 2 from dual union all
  4  select 2, 4 from dual union all
  5  select 3, 3 from dual
  6  /

Table created.

И запрос с использованием агрегатной функции LAST (http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions076.htm#sthref1540):

SQL> set autotrace on explain
SQL> select max(i) keep (dense_rank last order by j) i
  2       , max(j)
  3    from testmax
  4  /

         I     MAX(J)
---------- ----------
         2          4

1 row selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 44308443

------------------------------------------------------------------------------
| Id  | Operation          | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |         |     1 |    26 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE    |         |     1 |    26 |            |          |
|   2 |   TABLE ACCESS FULL| TESTMAX |     3 |    78 |     3   (0)| 00:00:01 |
------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement (level=2)

Также с одним сканированием таблицы, но с использованием аналитической функции для всех строк, гдес одним агрегатом все будет в порядке:

SQL> select i,j
  2    from (
  3      select i, j, max(j) over () max_j
  4        from testmax
  5    )
  6    where j=max_j
  7  /

         I          J
---------- ----------
         2          4

1 row selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1897951616

-------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |     3 |   117 |     3   (0)| 00:00:01 |
|*  1 |  VIEW               |         |     3 |   117 |     3   (0)| 00:00:01 |
|   2 |   WINDOW BUFFER     |         |     3 |    78 |     3   (0)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| TESTMAX |     3 |    78 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("J"="MAX_J")

Note
-----
   - dynamic sampling used for this statement (level=2)

Этот использует два сканирования таблицы вместо одного:

SQL> SELECT i, j
  2    FROM testmax
  3   WHERE j = ( SELECT MAX(j) from testmax )
  4  /

         I          J
---------- ----------
         2          4

1 row selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3795151209

-------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |     1 |    26 |     6   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL  | TESTMAX |     1 |    26 |     3   (0)| 00:00:01 |
|   2 |   SORT AGGREGATE    |         |     1 |    13 |            |          |
|   3 |    TABLE ACCESS FULL| TESTMAX |     3 |    39 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("J"= (SELECT MAX("J") FROM "TESTMAX" "TESTMAX"))

Note
-----
   - dynamic sampling used for this statement (level=2)

С уважением,
Роб.

3 голосов
/ 04 июня 2011
SELECT i, j
  FROM testmax
 WHERE j = ( SELECT MAX(j) from testmax )

Может возвращать более одной строки, если j не уникально.

1 голос
/ 04 июня 2011

Это может быть более эффективно, чем использование подзапроса.

select i,j
  from (
    select i, j, max(j) over () max_j
      from testmax
  )
  where j=max_j
  ;
1 голос
/ 04 июня 2011

Я думаю, вы можете упростить первый запрос, а затем мы можем использовать order by для очистки.

SELECT year, COUNT(*) AS c
FROM 
Movie M INNER JOIN ActedIn A ON M.movieID=A.MovieID
WHERE A.actorID=518238628
GROUP BY year
ORDER BY COUNT(*) DESC LIMIT 1;

Ваша СУБД может использовать SELECT TOP 1 вместо LIMIT 1.

0 голосов
/ 06 июня 2011

Правильнее использовать предложение having, когда вам нужно запросить агрегатные функции

select i, max(j)
  from testmax
 group by i
having max(j) = (select max(j) from testmax);

I                      MAX(J)                 
---------------------- ---------------------- 
2                      4                      

1 rows selected
...