2016-09-16 87 views
0

我需要產生將輸出類似的查詢:選擇基於字段值多行

NAME    GRADE SUBJECT 
Smith, Shirley   3  ELA 
Smith, Shirley   3   M 
Jones, John    5  ELA 
Jones, John    5   M 
Jones, John    5  SCI 

如果學生在5年級,8,或11,查詢應該產生3行數據每名學生。等級3,4,6,7,9,10和12應該只產生兩行數據。

我嘗試過使用聯合三個case語句的UNION ALL方法,但是這會給出'Missing Select keyword'錯誤。如果我從第一個UNION ALL和它下面的所有東西中刪除所有內容,查詢的頂部就可以正常工作。

什麼是更好的方法呢?

CASE 
    WHEN s.grade_level IN (3,4,5,6,7,8,9,10,11,12) THEN 
    SELECT 
     s.lastfirst as NAME, 
     s.grade_level as GRADE, 
     'ELA' as SUBJECT    
END 
FROM students s 

UNION ALL 

CASE 
    WHEN s.grade_level IN (3,4,5,6,7,8,9,10,11,12) THEN 
    SELECT 
     s.lastfirst as NAME, 
     s.grade_level as GRADE, 
     'M' as SUBJECT  
END 
FROM students s 

UNION ALL 

CASE 
    WHEN s.grade_level IN (5,8,11) THEN 
    SELECT 
     s.lastfirst as NAME, 
     s.grade_level as GRADE, 
     'SCI' as SUBJECT  
END 
FROM students s 

回答

1
WITH cteSubjects AS (
    SELECT 'ELA' AS Subject FROM dual 
    UNION ALL 
    SELECT 'M' FROM dual 
    UNION ALL 
    SELECT 'SCI' FROM dual 
) 

, cteGrades AS (
    SELECT 3 as grade_level 
    FROM dual 

    UNION ALL 

    SELECT c.grade_level + 1 
    FROM 
     cteGrades c 
    WHERE c.grade_level + 1 <= 12 
) 


SELECT * 
FROM 
    cteGrades g 
    INNER JOIN cteSubjects s 
    ON (CASE 
      WHEN g.grade_level IN (5,8,11) AND s.Subject = 'SCI' THEN 1 
      WHEN s.Subject <> 'SCI' THEN 1 
      ELSE 0 
     END) = 1 
    INNER JOIN students s 
    ON g.grade_level = s.grade_level 

雖然Throstens是正確的,你也許應該有查詢和關係表的檔次主題可以沒有。你可以使用Common Table Expression [CTE]來創建主題,然後遞歸cte來生成分數,然後將它們連接在一起,以獲得2或3個主題,然後簡單地將學生加入到它中。

+0

很棒的sql - 謝謝。我不得不稍微修改它,cteGrades AS語句生成「ORA-32039:遞歸WITH子句必須有列別名列表」,我用cteGrades(grade_level)AS解決了這個問題(...我同意Throsten的答案是首選,但我們並不總是在處理數據庫,我們可以編輯模式,就像我的情況一樣,我需要找到一個基於SQL的解決方案,而不是建議如何更改我的數據庫,Matt的解決方案效果很好。 –

1

將數據放在表格中而不是查詢中會更好。所以有與子類相關的等級?有這種關係的表,然後:

grade_subject

 
grade subject 
3  ELA 
3  M 
4  ELA 
4  M 
5  ELA 
5  M 
5  SCI 
6  ELA 
6  M 
... 

查詢:

select 
    s.lastfirst as name, 
    s.grade_level as grade, 
    gs.subject as subject 
from students s 
join grade_subject gs on gs.grade = s.grade_level 
order by s.lastfirst, gs.subject;