2013-06-29 65 views
3

我有3個表格。下面是結構:選擇其他表中缺少記錄的有效方法

  • studentid int, name varchar(20)
  • coursecourse_id int, subject varchar(10)
  • student_coursest_id int, course_id int) - >包含誰爲一療程

招收現在,我希望學生的名字寫一個查詢來找出沒有參加任何課程的學生。我可以看出,有多種方法可以獲取這些信息。你能否讓我知道哪一個是最有效率的,也是爲什麼。另外,如果有其他更好的執行方法,請告訴我。

db2 => select distinct name from student inner join student_course on id not in (select st_id from student_course) 

db2 => select name from student minus (select name from student inner join student_course on id=st_id) 

db2 => select name from student where id not in (select st_id from student_course) 

在此先感謝!

+2

我不知道爲什麼你會短語它作爲「連接vs正常」 - 根據我的經驗,*大多數*查詢至少包含一個連接。這就是說,我不會使用你的第一個例子,因爲它並不是真的以任何理智的方式使用連接(另一方面,「左連接」將是一個值得列入的列表)。但是關於SQL效率的大多數問題往往會更多地歸結爲可用的索引,而不會做太奇怪的事情(例如您的第一個查詢) –

+0

感謝您的回覆Damien!我同意第一個查詢實際上太奇怪了,幾乎沒有任何意義......我只是想探索選項。 – neha

回答

8

您使用的子查詢,無論是not inminus或其他什麼,通常都是低效的。要做到這一點常用的方式是left join

select name 
from student 
left join student_course on id = st_id 
where st_id is NULL 

使用join是「正常」和較受歡迎的解決方案。

+0

+1,但只有在我修復了延遲格式化之後。如果您必須恢復它,但是我的版本更具可讀性,畢竟這是我們對代碼進行格式化的原因。 – Bohemian

+1

@波希米亞嘿,什麼推遲: - /!它更簡潔! – TMS

+0

我不得不看「天氣」(我仍然不知道它是如何適用的),所以我在那裏學到了一些東西:)。你的格式不是我見過的最差的。最慢的格式選擇之一是左對齊每行的第二個*字,這是我看過的不止一次。 – Bohemian

0

使用「不在」通常是緩慢的。這使得你的第二個查詢是最有效的。儘管你可能不需要括號。

+3

是什麼讓你覺得'不在'是緩慢的而'minus'不是?我會說這兩個都很慢 – TMS

+0

@Tomas你能解釋一下,在這種情況下,連接比「不在」和「減」更好嗎? – neha

0

正如評論:我會建議選擇學生ID(這是唯一的),而不是名稱。

作爲具有計數(COURSE_ID),你可能想通過student_id數據加入兩個表,組數再查詢選項(COURSE_ID)= 0。

而且,我同意索引將是更重要的。

1

的規範(甚至天氣)成語是(恕我直言)使用NOT EXISTS

SELECT * 
FROM student st 
WHERE NOT EXISTS (
    SELECT * 
    FROM student_course 
    WHERE st.id = nx.st_id 
); 

優點:

  • NOT EXISTS(...)很老了,最優化器會知道如何處理它
  • ,因此它可能會出現在所有平臺上
  • nx.相關名稱不是泄漏到外部查詢中:外部查詢中的select *將僅產生student表中的字段,而不是student_course表中的(空)行(如LEFT JOIN ... WHERE ... IS NULL情況下)。這在具有大量範圍表項的查詢中特別有用。
  • (NOT) IN很容易出錯(空值),它可能會在一些實現執行不好的(重複和空值必須從不相關子查詢的結果中刪除)
相關問題