這個問題敘述乍看之下很簡單(符合某些成分的藥),但仔細想才覺得事情不是傻人的想的那麼簡單,問題的重點在於需要同時符合某幾個成分,這樣的藥有哪些,以下面的例子來看
SELECT [MedID] ,[MedName] FROM [Northwnd].[dbo].[MedTB]
SELECT [MedID] ,[SubMedName] FROM [Northwnd].[dbo].[SubMedTB]
SELECT MedTB.MedName,SubMedTB.SubMedName FROM SubMedTB INNER JOIN MedTB ON SubMedTB.MedID = MedTB.MedID
強力丸的成分有維他命A及維他命B,還魂丹有維他命A及維他命C,而十香軟筋散則是有維他命A、維他命B及維他命C,如果我想要找有維他命A的藥,則三種藥名都符合,但如果要同時有維他命A及維他命B的則有強力丸及十香軟筋散,同理有維他命A及維他命C的有環魂丹及十香軟筋散,但同時有維他命ABC的則只剩下十香軟筋散。這樣子的SQL查詢要怎麼下呢?我首先想到使用T-SQL中 INTERSECT的語法,假設我要找維他命A及維他命C的,則語法如下
SELECT MedTB.MedName FROM SubMedTB INNER JOIN MedTB ON SubMedTB.MedID = MedTB.MedID WHERE SubMedTB.SubMedName = N'維他命A' INTERSECT SELECT MedTB.MedName FROM SubMedTB INNER JOIN MedTB ON SubMedTB.MedID = MedTB.MedID WHERE SubMedTB.SubMedName = N'維他命B'
查詢到的結果如下
相同的道理,需要幾種成分同時符合的話,就繼續以SELECT組合INTERSECT與法即可達成,但是這樣的撰法方法,卻對於前端的程式呼叫造成極大的困擾,如果我的程式是規定不能組合SQL字串的話,那便不能用這個方法來解決(當然你可以把它寫進StoredProcedure or SQL Function也可,但一樣都需要判斷進來的成分參數來組合SQL),我比較prefer的是前端程式可以直接丟參數給既定的SQL即可,這樣才是我心目中優良的程式撰寫方式,最後請教 pinnywu大神後,給出這樣的SQL
SELECT MedName FROM ( SELECT MedTB.MedName,COUNT(1) as cnt FROM SubMedTB INNER JOIN MedTB ON SubMedTB.MedID = MedTB.MedID WHERE SubMedTB.SubMedName IN( N'維他命B' , N'維他命A') --參數內容 這裡可以直接丟參數 GROUP BY MedTB.MedName ) AS TA WHERE cnt = 2 -- IN中參數數量 這裡可以直接丟參數
這段SQL非常好玩,有興趣的可以先從sub select開始解讀,但我這裡要強調的是,這樣子的SQL才能避掉組SQL的方式,我只需要於前端程式中,於我註解的地方改成丟參數的方式,及可以把對應的參數傳入,例如如果我要找同時符合維他命ABC的,則會在IN的參數地方丟入維他命ABC的查詢結果,然後於cnt的地方丟恕我總共的參數數目是3,這個時候就可以查詢到十香軟筋散了,不知道各位看官懂不懂我再說什麼呢?
有興趣的大家可以討論一下。
註:其實如果都要組SQL了,那除了INTERSECT這種罕用關鍵字外,還有其他的方式可以解決這個問題。下次有機會再跟大家分享啦
沒有留言:
張貼留言