選擇兩個表中的一條記錄有三個表:在甲骨文
對學生的表:關於選擇課程
c41071030(cno, cname, cpno, credit)
一個表:
s41071030(sno, sname, ssex, sage, sdept)
有關課程的表:
sc41071030(sno, cno, grade)
現在,我想選擇一個sdept='CS'
的學生的詳細信息,他或她選擇了部門'CS'
中的最多課程。
選擇兩個表中的一條記錄有三個表:在甲骨文
對學生的表:關於選擇課程c41071030(cno, cname, cpno, credit)
一個表:s41071030(sno, sname, ssex, sage, sdept)
有關課程的表:sc41071030(sno, cno, grade)
現在,我想選擇一個sdept='CS'
的學生的詳細信息,他或她選擇了部門'CS'
中的最多課程。
雖然沒有經過測試,但是與您所尋找的東西類似。
select s.*
from s41071030 s join sc41071030 sc on s.sno = sc.sno
where s.sdept = 'CS' and (select count(sc41071030.cno)
from sc41071030 join c41071030
on sc41071030.cno = c41071030.cno group by sc41071030.sno) > 1
不是非常接近需要的東西。 –
與任何溫和複雜的SQL語句,最好是做「TDQD」 —測試驅動的查詢設計。從問題的簡單部分開始,將它們構建成更復雜的答案。
要找出多少課程,在CS部門每個學生走,我們寫:
SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno;
我們現在需要找到NumCourses的最大價值:
SELECT MAX(NumCourses) MaxCourses
FROM (SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
現在,我們需要將結果與子查詢結合在一起,因此是CTE(公用表表達式)的時間:
WITH N AS
(SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
SELECT N.Sno,
FROM N
JOIN (SELECT MAX(NumCourses) MaxCourses FROM N) M
ON M.MaxCourses = N.NumCourses;
,我們需要得到學生的詳細信息,所以我們加入一個與學生表:
WITH N AS
(SELECT S.Sno, COUNT(*) NumCourses
FROM s41071030 S
JOIN sc41071030 SC ON S.Sno = SC.Sno
WHERE S.Sdept = 'CS'
GROUP BY S.Sno
)
SELECT S.Sno,
FROM s41071030 S
JOIN N ON N.Sno = S.Sno
JOIN (SELECT MAX(NumCourses) MaxCourses FROM N) M
ON M.MaxCourses = N.NumCourses;
未經測試的SQL:你被警告。爲了測試,運行組件查詢,確保您每次都能獲得合理的結果。直到前一個查詢正常工作,才能繼續進行下一個查詢。
請注意,課程表對於您正在解決的查詢而言並不重要。
另請注意,如果發現有幾個學生全部參加相同數量的課程並且該數字是任何學生正在參加的最大數量,則可能會返回多行。 (所以,如果有3名學生服用,每次7門課程,並沒有學生服用超過7門課程,然後你會看到3行的結果集。)
總結sc41071030
行,以獲得計數。
加入結果s41071030
到:
濾波器行上sdept
;
獲取學生信息;
RANK()
計數值上的連接行。
與1
WITH aggregated AS (
SELECT
sno,
COUNT(*) AS coursecount
FROM sc41071030
GROUP BY sno
),
ranked AS (
SELECT
s.*,
RANK() OVER (ORDER BY agg.coursecount DESC) AS rnk
FROM sc41071030 s
INNER JOIN aggregated agg
WHERE s.sdept = 'CS'
)
SELECT
sno,
sname,
ssex,
sage,
sdept
FROM ranked
WHERE rnk = 1
@Jonathan Leffler:Re:在CTE中過濾的好處 - 我選擇在CTE中進行過濾,因爲這樣就不需要對整個'sc41071030'表進行排序(通過'sdept'對錶進行劃分),這可能會更有效。當然,如果sdept過濾器在主選擇中,優化器可能會發現不需要將RANK應用於所有行,而只應用於與指定的sdept匹配的那些行,但是我不能確定。而且我也讓我無需寫出'PARTITION BY ...'。 :) –
連接和聚合函數(這些都是你應該谷歌而言)會做的伎倆排名中選擇行。 – Anton
+1,用於在問題中包含表名和模式。 –