由一個博問學到的SQL查詢方法 (一道多對多關係查詢的面試題)

iSQlServer發表於2010-12-07

多對對關係查詢

 懸賞分:5 [已解決問題] 瀏覽:52 次
00

學生表  t1

Stu_id

Stu_name

1

張三

2

李四

3

王五

課程表  t2

Co_id

Co_name

1

Java

2

C#

3

C

4

C++

5

Javascript

關係表  t3

Stu_id

Co_id

1

1

1

4

2

1

2

3

2

5

前幾天去面試被問了一道關於資料庫的問題。到現在也沒找到答案。

題目是這樣的:有學生表、課程表和關係表,查出學生所選的課程。

我當時就想通過連線查詢。當然這樣的話會出現重複出現同一個學生姓名的情況。如:

張三

Java

張三

C++

可是題目要求出現的情況是:張三 java,c++

請問這個SQL該如何寫。


]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]盪漾的分割線]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]


當時看到這個博問後,仔細想了以前學的SQL知識,發現似乎只能先把查詢結果賦值給變數,然後再查詢一次。但這個題目的意思顯然不是這樣做的,於是我把問題發到快閃記憶體區期望高手解答。今天上班後開啟看了下,發現已經有了答案,於是在自己資料庫實驗了下,結果答案不完整直接執行失敗。於是我仔細看了下答案內容,發現了2個不認識的東東 stuff()函式 和 for xml path。之後我就去網上搜尋關於這2個的意義。


stuff(str1,start,length,str2)比較簡單,是一個可以設定起始位置的替換字串函式。
str1是原始字串。
start是要替換的起始位置。
length是要替換原始字串內容的長度。
str2是替換的新內容。
例子:stuff('12345',2,2,'000') 的結果為'100045',既'12345'的第二位'2'開始,長度為二,既'23',替換為'000',得到結果'100045'。當然也有其他的簡單方法可以做到同樣效果


for xml path則複雜一些,是將查詢到的結果生成XML資料。具體用法可以去這裡看http://www.docin.com/p-73893088.html


大致上對for xml path似懂非懂後我就開始嘗試。


先是通過幾次嘗試後寫出 select ','+co_name from t2 where co_id=1 or co_id=2 for xml path('') 查詢得到 ".java.C#"


然後確定了方向,我需要通過 t3 表中的 stu_id 找出相關聯的 co_id,然後通過上面的語句就能得到正確的答案。


解題思路正確了,得到答案不過是水到渠成的問題,通過多次嘗試,得到語句 


select distinct stu_id,(select convert(varchar(20),co_id)+',' from t3 where a.stu_id=stu_id for xml path('')) from t3 a


成功按照要求查出了學生ID對應的課程ID,之後將學生ID換成學生Name


select distinct stu_name,(select convert(varchar(20),co_id)+',' from t3 where a.stu_id=stu_id for xml path('')) from t3 a,t1 b where a.stu_id=b.stu_id


再之後將課程ID換成課程Name,並且使用stuff()函式將第一個','替換為空


select distinct stu_name,stuff((select ','+co_name from t3,t2 where a.stu_id=stu_id and t3.co_id=t2.co_id for xml path('')),1,1,'') from t3 a,t1 b where a.stu_id=b.stu_id


這就已經是問題所需要的正確答案了,由於是自己打草稿寫著玩,程式碼相當混亂,多表查詢寫的也不規範,而且我只是個小菜鳥,歡迎高手寫出來簡潔,優雅的查詢語句供我學習。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16436858/viewspace-681073/,如需轉載,請註明出處,否則將追究法律責任。

相關文章