1. 程式人生 > >一條SQL查詢出每門課程的成績都大於80的學生姓名是一道有歧義的題嗎?

一條SQL查詢出每門課程的成績都大於80的學生姓名是一道有歧義的題嗎?

‘用一條SQL語句查詢出每門課程的成績都大於80的學生姓名’是一道歧義題嗎?
name   kecheng    fenshu 
張三     語文             81
張三     數學             90
李四     語文             76
李四     數學             90
王五     語文             81
王五     數學             100
王五     英語             90
用一條SQL語句查詢出每門課程的成績都大於80的學生姓名。

這時一道比較經典的資料庫方面的面試題,經常出現在各種面試筆試中,主要考察應試者資料庫功底。

這道題有兩種理解思路:

第一種是出現在表裡面的課程就是該人的所有課程,即張三李四在沒有英語成績下,兩門都大於80也是算每門都大於80。

第二種是他們都有英語數學語文三門課程,沒有出現在表的成績要按0來算,即張三李四還有一門成績為0的英語。

我查閱一些相關的資料,發現大家都是以第一種來程式設計的,下面我來寫下這兩種的相關SQL。
至於那種是正確的憑君來斷,亦或留下你的見解。

第二種的正確的思路是:查詢出某個人的最小成績是否大於80並且這個人的課程數是3門。

1、用not in 或者 not exists 實現 第一種的寫法 不過DISTINCT關鍵字儘量少用,效率太低

	//not in 
	SELECT DISTINCT A.name FROM Student A 
	WHERE A.name not in(
	SELECT Distinct S.name FROM Student S WHERE S.score <80);

	//not exists
	SELECT DISTINCT A.name From Student A  
	where not exists (SELECT 1 From Student S Where  S.score <80 AND S.name =A.name);
第二種通俗寫法,效率不高:
	select distinct A.Name
	  from table1 A
	 where a.name not in (select u.name
					from (select s.name,
					        s.fenshu,
						count(s.name) over(partition by s.name) count1
						from table1 s) u
				 where u.fenshu < 80
				or count1 < 3);	

2、第一種寫法是,效率比較高:

	SELECT S.name
	FROM Student S
	GROUP BY S.name
	Having MIN(S.score)>=80 ;
在上面的那些資料確實可以得到王五,但是當張三或者李四語文數學都是大於80的時候,就會查詢出來所有的名字。

第二種效率高的寫法:

	select A.Name
	  from table1 A
	 group by A.Name
	having count(1) = 3 and min(a.fenshu) >= 80;
另外一種等價的寫法:
	select t.name
	  from (select d.name,
			d.kecheng,
			(case
			when to_number(d.fenshu, '990.99') >= 80 then
			 1
			else
			 0
			 end) cnt
			  from table1 d) t
	 group by t.name
	having sum(t.cnt) >= 3;

猿友們你覺得那種是正確的思路那?請不吝點評,共同探討。


每天努力一點,每天都在進步。