SQL Server:如何从动态列的值中计数?
我有数据:
+ Subject ___________________ | SubID | SubName | |-------|---------| | 1 | English | |-------|---------| | 2 | Spanish | |-------|---------| | 3 | Korean | |_______|_________| + Student ______________________________________ | StuID | StuName | Gender | SubID | |---------|---------|--------|--------| | 1 | David | M | 1,2 | |---------|---------|--------|--------| | 2 | Lucy | F | 2,3 | |_________|_________|________|________|
我想查询结果为:
____________________________________ | SubID | SubName | Female | Male | |--------|---------|--------|------| | 1 | English | 0 | 1 | |--------|---------|--------|------| | 2 | Spanish | 1 | 1 | |--------|---------|--------|------| | 3 | Koean | 1 | 0 | |________|_________|________|______|
这是我的查询
SELECT SubID, SubName, 0 AS Female, 0 AS Male FROM Subject
我不知道用实际计数替换0。
答案 0 :(得分:2)
由于您在表中存储CSV数据时出错,因此我们将不得不执行一些SQL Olympics来获取结果集。我们可以尝试合并两个表,但前提是主题表中的SubID
出现在学生表ID的CSV列表中的某个位置。然后,按主题汇总并计算男性和女性的人数。
SELECT
s.SubID,
s.SubName,
COUNT(CASE WHEN st.Gender = 'F' THEN 1 END) Female,
COUNT(CASE WHEN st.Gender = 'M' THEN 1 END) Male
FROM Subject s
LEFT JOIN Student st
ON ',' + CONVERT(varchar(10), st.SubID) + ',' LIKE
'%,' + CONVERT(varchar(10), s.SubID) + ',%'
GROUP BY
s.SubID,
s.SubName;
但是,最好重构表设计以更好地规范化数据。这是一个看起来更好一些的学生桌示例:
+---------+---------+--------+--------+
| StuID | StuName | Gender | SubID |
+---------+---------+--------+--------+
| 1 | David | M | 1 |
+---------+---------+--------+--------+
| 1 | David | M | 2 |
+---------+---------+--------+--------+
| 2 | Lucy | F | 2 |
+---------+---------+--------+--------+
| 2 | Lucy | F | 3 |
+---------+---------+--------+--------+
我们可以走得更远,甚至可以将元数据与StuID
和SubID
关系分开存储。但是,即使仅使用上述方法,也可以避免出现丑陋的连接条件。
答案 1 :(得分:0)
如果您的SQL Server版本是SQL Server或更高版本,则可以使用STRING_split函数来获得预期的结果。
create table Subjects
(
SubID int,
SubName varchar(30)
)
insert into Subjects values
(1,'English'),
(2,'Spanish'),
(3,'Korean')
create table student
(
StuID int,
StuName varchar(30),
Gender varchar(10),
SubID varchar(10)
)
insert into student values
(1,'David','M','1,2'),
(2,'Lucy','F','2,3')
--Query
;WITH CTE AS
(
SELECT
S.Gender,
S1.value AS SubID
FROM student S
CROSS APPLY STRING_SPLIT(S.SubID,',') S1
)
select
T.SubID,
T.SubName,
COUNT(CASE T1.Gender WHEN 'F' THEN 1 END) AS Female,
COUNT(CASE T1.Gender WHEN 'M' THEN 1 END) AS Male
from Subjects T
LEFT JOIN CTE T1 ON T.SubID=T1.SubID
GROUP BY T.SubID,T.SubName
ORDER BY T.SubID
--Output
/*
SubID SubName Female Male
----------- ------------------------------ ----------- -----------
1 English 0 1
2 Spanish 1 1
3 Korean 1 0
*/