2012-10-15 119 views
2

我有一個名爲學生爲遵循表:使用AVG()中的Oracle SQL

CREATE TABLE "STUDENT" 
( "ID" NUMBER(*,0), 
    "NAME" VARCHAR2(20), 
    "AGE" NUMBER(*,0), 
    "CITY" VARCHAR2(20), 
    PRIMARY KEY ("ID") ENABLE 
) 

我想獲得具有比平均年齡更大的年齡學生的所有記錄。這是我的嘗試:

SELECT * 
FROM student 
WHERE age > AVG(age) 

SELECT * 
FROM student 
HAVING age > AVG(age) 

兩種方式都沒有工作!

回答

9

如果您打算使用沒有組的聚合,則不能引用其他字段。 (你與*)

但是你可以做一個子查詢。

SELECT * 
FROM student 
WHERE age > (SELECT AVG(age) FROM STUDENT) 

這很容易寫和理解。但是,如果使用分析函數,則可以獲得更好的性能,因爲Justin Cave explains in his answer

+0

謝謝,它工作 –

5

Conrad Fix suggested是傳統方法的子查詢方法。然而,這不太可能是最有效的方法,因爲它要求甲骨文兩次上榜 - 一次是計算平均年齡,一次是拉回薪水高於平均水平的行。如果您使用分析函數,則可以完成相同的工作,而只需執行一次表格並執行(大致)一半邏輯I/O操作。

select * 
    from (select s.*, avg(age) over() avg_age 
      from student s) 
where age > avg_age 

的傳統方法需要18一致獲取和必須做表的兩個全掃描(請注意,我跑了兩個測試幾次,以獲得最低值排除之類的延遲塊清除)

SQL> ed 
Wrote file afiedt.buf 

    1 select * 
    2 from hr.employees 
    3 where salary > (select avg(salary) 
    4*     from hr.employees) 
SQL>/

51 rows selected. 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 1945967906 

--------------------------------------------------------------------------------- 
| Id | Operation   | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |   |  5 | 345 |  6 (0)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL | EMPLOYEES |  5 | 345 |  3 (0)| 00:00:01 | 
| 2 | SORT AGGREGATE |   |  1 |  4 |   |   | 
| 3 | TABLE ACCESS FULL| EMPLOYEES | 107 | 428 |  3 (0)| 00:00:01 | 
--------------------------------------------------------------------------------- 

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

    1 - filter("SALARY"> (SELECT AVG("SALARY") FROM "HR"."EMPLOYEES" 
       "EMPLOYEES")) 


Statistics 
---------------------------------------------------------- 
      0 recursive calls 
      0 db block gets 
     18 consistent gets 
      0 physical reads 
      0 redo size 
     5532 bytes sent via SQL*Net to client 
     557 bytes received via SQL*Net from client 
      5 SQL*Net roundtrips to/from client 
      0 sorts (memory) 
      0 sorts (disk) 
     51 rows processed 

的解析函數的方法,但是,確實在一個表中同樣的事情,只有7一致掃描得到

SQL> select * 
    2 from (select e.*, avg(salary) over() avg_salary 
    3   from hr.employees e) 
    4 where salary > avg_salary 
    5/

51 rows selected. 


Execution Plan 
---------------------------------------------------------- 
Plan hash value: 48081388 

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

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

    1 - filter("SALARY">"AVG_SALARY") 


Statistics 
---------------------------------------------------------- 
      1 recursive calls 
      0 db block gets 
      7 consistent gets 
      0 physical reads 
      0 redo size 
     5220 bytes sent via SQL*Net to client 
     557 bytes received via SQL*Net from client 
      5 SQL*Net roundtrips to/from client 
      1 sorts (memory) 
      0 sorts (disk) 
     51 rows processed 

正如康拉德指出,雖然,分析本功能離子方法需要進行分類,所以它應該比傳統方法使用更多的PGA。增加內存你將會減少I/O。通常這是一個理想的折衷,但這是你應該知道的。

+2

+1非常不錯的選擇,雖然值得注意的是,正如你的數據顯示的那樣,你正在交易RAM的CPU/IO。 –

+0

我開悟了一下。謝謝! –