SQL Server:如何从动态列的值中计数?

时间:2018-12-25 08:33:08

标签: sql-server

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。

2 个答案:

答案 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;

enter image description here

Demo

但是,最好重构表设计以更好地规范化数据。这是一个看起来更好一些的学生桌示例:

+---------+---------+--------+--------+
| StuID   | StuName | Gender | SubID  |
+---------+---------+--------+--------+
| 1       | David   | M      | 1      |
+---------+---------+--------+--------+
| 1       | David   | M      | 2      |
+---------+---------+--------+--------+
| 2       | Lucy    | F      | 2      |
+---------+---------+--------+--------+
| 2       | Lucy    | F      | 3      |
+---------+---------+--------+--------+

我们可以走得更远,甚至可以将元数据与StuIDSubID关系分开存储。但是,即使仅使用上述方法,也可以避免出现丑陋的连接条件。

答案 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
*/