2013-10-29 71 views
3

我有一些領域和樣本記錄數據庫表通過如下圖所示:SQL - 讓學生誰在所有科目

Name Test Result Other_fields 
A  English P   x 
B  Maths  F   x 
C  English P   x 
B  English P   x 
A  Maths  F   x 
D  English P   x 
C  Biology F   x 
A  Biology P   x 
B  Biology F   x 

現在的實際表中包含了很多各種各樣的測試。
我想要達到的是找到一個學生的數量/列表(以及其他字段中對於學生來說唯一的相應數值,例如他的年齡,性別等)誰通過了所有在逗號中指定的測試 - 分隔字符串。該字符串顯然是在運行時插入到查詢中的。

現在,如果它是一個固定數量的測試說2個測試或3個測試,那麼我可以爲它寫一個查詢。
但真正的問題是CSV字符串中的測試數量不固定。
有什麼辦法可以實現這個目標嗎?如果有人計劃提出一個涉及使用SQL IN的答案,我可以用一些唯一的數字替代測試名稱(作爲測試ID)。

編輯

顯然,我沒有讓自己很清楚。該表將包含大量測試的記錄(比如test1,test2,... test100)。 CSV字符串將包含一些測試(例如2或3或4,但絕對超過1)。而且我希望學生在通過CSV字符串指定的所有測試中通過的數據。

EDIT 2
可以有對應於學生的一個組合和測試(多次及格和不及格)

+0

你從哪裏得到CSV字符串?如果測試名稱中包含逗號,會發生什麼情況?您應該避免使用CSV字符串進行編碼。如果這不可能,那麼在嘗試使用它來查詢Oracle之前,應該解析它。 –

+0

用戶可以多次進行一次測試嗎?如果是的話,那麼如果他至少失敗了一次,那麼這個學生是否應該被包括進來?如果您有測試要通過單獨的表格,並且您需要檢查學生是否至少通過了一次這些測試,那麼解決方案非常簡單。 –

回答

3
SELECT DISTINCT Name 
    FROM Table t 
WHERE NOT EXISTS(SELECT 1 
        FROM Table 
        WHERE  t.Name = Name 
         AND Result = 'F' 
         AND ',' || CsvOfTests || ',' LIKE '%,' || Test || ',%' 
       ) 

我會建議使用像自動增加一些獨特的價值多條記錄id而不是這裏的名字。如果要在結果集中包含其他字段,可以將它們包含在SELECT和GROUP BY字段列表中,或使用連接。

CsvOfTests是您感興趣的測試列表。我在CsvOfTests和Test的開頭和結尾添加了逗號,一個測試的名稱是其他測試名稱的子字符串。 但是我不得不說,我覺得如果你將測試放到臨時表而不是csv字符串中,那麼查詢會簡單得多,而且不那麼黑。

如果你的輸入字符串不只是用逗號分隔測試(就像用逗號後面的空格分隔,你還需要包括這些)。如果它比這更復雜,那麼我想我會嘗試REGEXP_LIKE或編寫我自己的函數。

每請求計數通過科目

SELECT DISTINCT Name 
    FROM Table t 
WHERE LENGTH(CsvOfTests) - LENGTH(REPLACE(CsvOfTests, ',')) + 1 = (
        SELECT COUNT(1) 
        FROM Table 
        WHERE  t.Name = Name 
         AND Result = 'P' 
         AND ',' || CsvOfTests || ',' LIKE '%,' || Test || ',%' 
       ) 

這裏LENGTH(CsvOfTests) - LENGTH(REPLACE(CsvOfTests, ',')) + 1計數在列表中的測試數查詢。然後它只是指出學生已經通過了多少次這些測試。顯然,REGEXP_COUNT也可以在11g第1版中做到這一點。

當我重讀並考慮了您的問題後,我明白這不完全是您要求的。這個查詢的目的更多的是檢查學生是否通過了每門科目(即如果你第一次考試失敗,那麼你重新考試並最終通過考試)。

+0

我不希望它的所有測試....只有CSV字符串指定的測試....其確定如果學生在其他測試失敗...我想我沒有說清楚... .my道歉 – tumchaaditya

+0

我必須在我能說任何事之前測試這個。我確實打算使用唯一的測試ID而不是測試名稱...不......我已經注意到它會被逗號分隔.. – tumchaaditya

+0

如果一個人爲一個主題進行多次嘗試,這種方式是否可行? – tumchaaditya

1

您想查找如何將csv轉換爲表格。我從來沒有爲Oracle做過這件事,但它應該很容易做到。

或者,考慮您是否確實需要發送csv,或者您可以發送多個參數。像Test in (param1,param2,....paramX)。如果你允許有限的參數,這是可行的。如果你發送數千個參數,那麼它當然是行不通的,但是如果你總是發送3-5個參數,它就可以正常工作。

編輯︰這是一個sqlfiddle,基本上顯示我的意思,以及如何做到這一點。它分割一個字符串,加入字符串,計算匹配測試的次數,並列出學生通過所有輸入測試的學生/測試信息。我的原始示例在1 = 1時加入了一個連接,因爲我在列名中遇到了問題,並且想要顯示連接發生的情況。

With t as (
Select 'English, Biology' as Tests from dual 
), 
Spl as(
Select rtrim(ltrim(REGEXP_SUBSTR (Tests, '[^,]+', 1, level))) As Tst, 
regexp_count(Tests,'[,]')+1 NumberOfTest 
from t 
connect by level<= regexp_count(Tests,'[,]')+1 
) 
, StudentPassing as (
Select count(TestName) over (partition by StudentName) TestPassed, 
    s.*, NumberOfTest 
from StudentTest s 
    inner join Spl 
    on Tst=TestName 
where TestResult='P' 
) 
select * 
from StudentPassing 
where TestPassed=NumberOfTest 
+0

我不知道我跟隨你想說的多個參數.. ..他們都在數據庫中的單個字段.. – tumchaaditya

+0

我會考慮你的第一個建議..你如何建議我去那裏(我知道如何創建一個CSV字符串表).. – tumchaaditya

+0

曾經你有一張他們必須採取的測試表,簡單地加入,然後你計數/不同的價值。 – jmoreno

相關問題