2017-07-01 120 views
0

我有一個數據庫期末考試,當我解決一些樣本問題時,我遇到了一些問題。SQL-INTERSECT with HAVING + MAX of SUM

我有兩個表之間的多對多關係。

Player     PlayerTournament    Tournament 
-------     --------------------   ------------------- 
pk id_player    fk id_player     pk id_tournament 
name      fk id_tournament    name 
rank      year       city 
country     victories      court_surface 
                 tournament_type 

我要做的是:

1)。列出2016年在紅土錦標賽中贏得至少一場比賽但沒有參加任何草地錦標賽的球員(姓名和國家)。 2)。列出勝利數最多的球員(名字,國家,勝利總數)。

我在想是這樣的:

1. SELECT P.NAME, P.COUNTRY 
FROM Player P INNER JOIN PlayerTournament PT 
ON P.ID_PLAYER= PT.ID_PLAYER 
INNER JOIN Tournament T 
ON T.ID_TOURNAMENT= PT.ID_TOURNAMENT 
WHERE T.COURT_SURFACE="clay" 
GROUP BY (something) 
HAVING SUM(PT.VICTORIES)>=1 
INTERSECT 
(same select and inner joins) 
WHERE T.COURT_SURFACE="grass" 
GROUP BY (something) 
HAVING COUNT(ID_PLAYER)=0 

2.SELECT P.NAME, P.COUNTRY, SUM(PT.VICTORIES) 
FROM Player P INNER JOIN PlayerTournament PT 
ON P.ID_PLAYER= PT.ID_PLAYER 
GROUP BY ... 
HAVING sum of victories = max sum of victories 

我不知道如果我的方式思考的問題是正確的,我需要用「具有」語句幫助。

回答

0

Q1:INTERSECT將不起作用,因爲COUNT(ID_PLAYER)永遠不會爲NULL。 您必須切換到EXCEPT而不是HAVING

對於這種類型的查詢的另一個標準溶液(相同與不同條件選擇)利用有條件聚集其中兩個條件都移動到不同的情況:

SELECT P.NAME, P.COUNTRY 
FROM Player P INNER JOIN PlayerTournament PT 
ON P.ID_PLAYER= PT.ID_PLAYER 
INNER JOIN Tournament T 
ON T.ID_TOURNAMENT= PT.ID_TOURNAMENT 
WHERE T.COURT_SURFACE IN ('clay', 'grass') 
GROUP BY (something) 
HAVING SUM(CASE WHEN T.COURT_SURFACE = 'clay' THEN PT.VICTORIES END)>=1 
AND COUNT(CASE WHEN T.COURT_SURFACE = 'grass' THEN PT.ID_PLAYER END)=0 

Q2:這似乎索要最好球員每個國家,但你不能直接編寫爲嵌套聚合罕見不允許。您可以使用,而不是相關子查詢:

WITH cte AS 
(
    SELECT P.NAME, P.COUNTRY, SUM(PT.VICTORIES) AS sumVic 
    FROM Player P INNER JOIN PlayerTournament PT 
    ON P.ID_PLAYER= PT.ID_PLAYER 
    GROUP BY ... 
) 
SELECT * 
FROM cte AS t1 
WHERE sumVic = 
(SELECT MAX(sumVic) 
    FROM cte AS t2 
    WHERE t1.ID_PLAYER = t2.ID_PLAYER 
) 

使用更現代化的窗聚合函數你能做的MAX-計算在同一水平線上:

WITH cte AS 
(
    SELECT P.NAME, P.COUNTRY, SUM(PT.VICTORIES) AS sumVic, 
     MAX(SUM(PT.VICTORIES)) OVER (PARTITION BY P.COUNTRY) AS maxVic 
    FROM Player P INNER JOIN PlayerTournament PT 
    ON P.ID_PLAYER= PT.ID_PLAYER 
    GROUP BY ... 
) 
SELECT * 
FROM cte AS t1 
WHERE sumVic = maxVic