具有列标题和计数的列名/基于其他表中列标签的数据透视
Posted
技术标签:
【中文标题】具有列标题和计数的列名/基于其他表中列标签的数据透视【英文标题】:Column name with column caption and count / Pivot based on column label in other table 【发布时间】:2014-01-24 03:06:33 【问题描述】:我有两张表如下:
TABLE 标记列表:
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 的结果。我可能走错了方向,但我不知道。
【问题讨论】:
从长远来看,进一步规范化数据可能会为您提供更好的服务;重复的列通常是设计缺陷的标志。 @Clockwork-Muse- 有时我们都有义务接受事物的本来面目而不改变它们,不是吗?这对我来说就是其中之一。 【参考方案1】:你可以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 上的演示。
【讨论】:
您的回答绝对有用,但在您发布之前,我自己已经找到了解决方案。无论如何,谢谢。【参考方案2】:试试这个
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
【讨论】:
怎么样?你这么说的依据是什么? 使用join来检索结果。【参考方案3】:我找到了答案。您可以跳过 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
【讨论】:
以上是关于具有列标题和计数的列名/基于其他表中列标签的数据透视的主要内容,如果未能解决你的问题,请参考以下文章