2011-04-29 69 views
4

我正在查詢Oracle 10g中的報表。SQL查詢自加入

我需要生成每個課程的簡短列表以及過去一年提供的次數(包括實際未提供的次數)。

我創建一個查詢

SELECT coursenumber, count(datestart) AS Offered 
FROM class 
WHERE datestart BETWEEN (sysdate-365) AND sysdate 
GROUP BY coursenumber; 

將會產生

COURSENUMBER OFFERED 
----   ---------- 
ST03    2 
PD01    1 
AY03    2 
TB01    4 

此查詢正確的。但理想情況下,我希望它在左列中列出COURSENUMBER HY和CS以及0或null作爲OFFERED值。我有一種感覺,這涉及到各種各樣的連接,但到目前爲止,我所嘗試過的不會產生沒有提供任何東西的類。

表通常看起來像

REFERENCE_NO DATESTART TIME TIME  EID  ROOMID COURSENUMBER 
------------ --------- ---- ---- ---------- ---------- ---- 
     256 03-MAR-11 0930 1100   2   2 PD01 
     257 03-MAY-11 0930 1100   12   7 PD01 
     258 18-MAY-11 1230 0100   12   7 PD01 
     259 24-OCT-11 1930 2015   6   2 CS01 
     260 17-JUN-11 1130 1300   6   4 CS01 
     261 25-MAY-11 1900 2000   13   6 HY01 
     262 25-MAY-11 1900 2000   13   6 HY01 
     263 04-APR-11 0930 1100   13   5 ST03 
     264 13-SEP-11 1930 2100   6   4 ST03 
     265 05-NOV-11 1930 2100   6   5 ST03 
     266 04-FEB-11 1430 1600   6   5 ST03 
     267 02-JAN-11 0630 0700   13   1 TB01 
     268 01-FEB-11 0630 0700   13   1 TB01 
     269 01-MAR-11 0630 0700   13   1 TB01 
     270 01-APR-11 0630 0700   13   1 TB01 
     271 01-MAY-11 0630 0700   13   1 TB01 
     272 14-MAR-11 0830 0915   4   3 AY03 
     273 19-APR-11 0930 1015   4   3 AY03 
     274 17-JUN-11 0830 0915   14   3 AY03 
     275 14-AUG-09 0930 1015   14   3 AY03 
     276 03-MAY-09 0830 0915   14   3 AY03 

回答

1

我覺得這樣的事情應該爲你工作,通過只是在做它作爲一個子查詢。

SELECT distinct c.coursenumber, 
     (SELECT COUNT(*) 
     FROM class 
     WHERE class.coursenumber = c.coursenumber 
      AND datestart BETWEEN (sysdate-365) AND sysdate 
     ) AS Offered 
FROM class c 
+0

非常感謝!我不知道你可以有一個子查詢作爲聲明的選擇x,y,z部分的一部分。 – tyh 2011-04-29 15:21:41

+0

@timyh沒問題,很高興我能幫忙,並歡迎來到SO。 – 2011-04-29 15:35:43

1

我喜歡jschoen的回答這種特殊情況下更好的(當你想要一個且只有一個行和列出來的子查詢爲主查詢的每一行),但只是爲了展示另一種方式來做到這一點:

select t1.coursenumber, nvl(t2.cnt,0) 
from class t1 left outer join (
select coursenumber, count(*) cnt 
from class 
where datestart between (sysdate-365) AND sysdate 
group by coursenumber 
) t2 on t1.coursenumber = t2.coursenumber 
+0

你介意解釋nvl(t2.cnt,0)部分嗎?我認爲你指的是t2.cnt,但「nvl」是做什麼的,最後的「0」的意義是什麼? – tyh 2011-04-29 16:02:04

+0

@timyh:你說這是Oracle,對吧?那麼,nvl()是一個Oracle函數。其他一些數據庫也有,或者至少類似。 – runrig 2011-04-30 05:09:36

2
SELECT 
    coursenumber, 
    COUNT(CASE WHEN datestart BETWEEN (sysdate-365) AND sysdate THEN 1 END) AS Offered 
FROM class 
GROUP BY coursenumber; 

所以,你可以看到,這個特定的問題並不需要一個連接。

+0

也是一個工作解決方案。 「THEN 1 END」是做什麼的? – tyh 2011-04-29 18:59:58

+0

它是[CASE](http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/expressions004.htm)表達式的一部分。基本上,CASE表達式如下所示:'CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ... ELSE default_result END'。 'ELSE'部分是可選的,省略時默認爲'ELSE NULL'。在我的例子中1是一個任意值,我可以使用任何東西,而不是NULL,因爲COUNT不計數NULL。因此,CASE在條件爲真時返回一個值,並計算該值。當條件爲false時,返回NULL(不計數)。 – 2011-04-29 19:10:01