具有列标题的列名和基于其他表中的列标签的count / Pivot

时间:2014-01-24 03:06:33

标签: sql oracle pivot

我有两张表如下:

TABLE marklist:

student_id  class_id    subject_1   subject_2   subject_3   subject_4   subject_5
----------- ----------- ----------- ----------- ----------- ----------- ----------
1           9           78          87                                  95
2           9           67          95                                    87
3           9           85          84                                    85
4           10          70                      65          78    
5           10          75                      80          81    
6           10          80                      75          82    

表subject_names

column_name     subject_name
--------------- -------------
subject_1       English
subject_2       Chemistry
subject_3       Economics
subject_4       Accounts
subject_5       Biology

现在,我需要为class_id = 9

生成这样的报告
column_name     subject_name  no_of_students
--------------- ------------- --------------
subject_1       English       3
subject_2       Chemistry     3
subject_3       Economics     0
subject_4       Accounts      0
subject_5       Biology       3

简而言之,我必须生成一个包含column_names,subject_name和来自class_id = 9(或10,无论如何)的学生人数的报告。

我所能做的就是

1

    SELECT sn.column_name, sn.subject_name FROM subject_names sn;

2

    SELECT ml.class_id,
           count(ml.subject_1) AS s1,
           count(ml.subject_2) AS s1,
           count(ml.subject_3) AS s1,
           count(ml.subject_4) AS s1,
           count(ml.subject_5) AS s1,
      FROM marklist ml
     WHERE ml.class_id = 9;

我不明白如何继续使用查询1来转移查询2的结果。我可能会走错方向,但我没有想法。

3 个答案:

答案 0 :(得分:2)

您可以unpivot您的marklist表,并将其与subject_names表连接。

with unpivot_x(student_id,class_id,subject_code,marks) as (
    select * from marklist
    unpivot (marks for subject_code in (  subject_1 as 'subject_1',
                                          subject_2 as 'subject_2',
                                          subject_3 as 'subject_3',
                                          subject_4 as 'subject_4',
                                          subject_5 as 'subject_5'
                                      )
                                      ))
select a.column_name,a.subject_name, count(b.student_id)
  from subject_names a left outer join unpivot_x b
    on a.column_name = b.subject_code and b.class_id = 9
 group by a.column_name,a.subject_name
 order by 1;

sqlfiddle的演示。

答案 1 :(得分:0)

我找到了答案。您可以跳过CTE并检查以下主要查询:

/* -- This WITH clause is just for your reference.
WITH marklist AS (
SELECT 1 student_id, 9 class_id, 78 subject_1,87 subject_2,
       null subject_3, null subject_4, 95 subject_5 FROM dual
UNION ALL SELECT 2, 9, 67,95, null, null, 87 FROM dual
UNION ALL SELECT 3, 9, 85,84, null, null, 85 FROM dual
UNION ALL SELECT 4, 10,70, null, 65,78, null FROM dual
UNION ALL SELECT 5, 10,75, null, 80,81, null FROM dual
UNION ALL SELECT 6, 10,80, null, 75,82, null FROM dual
)
, subject_names AS (
SELECT 'subject_1' column_name, 'English' subject_name FROM dual
UNION ALL SELECT 'subject_2', 'Chemistry' FROM dual
UNION ALL SELECT 'subject_3', 'Economics' FROM dual
UNION ALL SELECT 'subject_4', 'Accounts' FROM dual
UNION ALL SELECT 'subject_5', 'Biology' FROM dual
) -- */
SELECT sn.column_name, sn.subject_name,
       (SELECT COUNT(CASE sn.column_name
                        WHEN 'subject_1' THEN ml.subject_1
                        WHEN 'subject_2' THEN ml.subject_2
                        WHEN 'subject_3' THEN ml.subject_3
                        WHEN 'subject_4' THEN ml.subject_4
                        WHEN 'subject_5' THEN ml.subject_5
                      END)
           FROM marklist ml
          WHERE ml.class_id = 9) AS no_of_students
  FROM subject_names sn;

<强>输出:

column_name    subject_name    no_of_students
-------------- --------------- --------------
subject_1      English         3
subject_2      Chemistry       3
subject_3      Economics       0
subject_4      Accounts        0
subject_5      Biology         3

答案 2 :(得分:0)

试试这个

SELECT a.column_name, a.subject_name, COUNT( subject_1 ) 
FROM subject_names a
JOIN mark_list b ON b.class_id =9
AND a.subject_name =  'English'
GROUP BY a.subject_name
UNION ALL SELECT a.column_name columnname, a.subject_name, COUNT( subject_3 ) 
FROM subject_names a
JOIN mark_list b ON b.class_id =9
AND a.subject_name =  'Chemistry'
GROUP BY a.subject_name
UNION ALL SELECT a.column_name columnname, a.subject_name, COUNT( subject_4 ) 
FROM subject_names a
JOIN mark_list b ON b.class_id =9
AND a.subject_name =  'Economics'
GROUP BY a.subject_name UNION ALL 
SELECT a.column_name columnname, a.subject_name, COUNT( subject_2 ) 
FROM subject_names a
JOIN mark_list b ON b.class_id =9
AND a.subject_name =  'Accounts'
GROUP BY a.subject_name
UNION ALL 
SELECT a.column_name columnname, a.subject_name, COUNT( subject_1 ) 
FROM subject_names a
JOIN mark_list b ON b.class_id =9
AND a.subject_name =  'Biology'
GROUP BY a.subject_name