【问题标题】:SQL Server: how count from value from dynamic columns?SQL Server:如何从动态列的值中计数?
【发布时间】:2018-12-25 17:54:30
【问题描述】:

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

+ 主题 ___________________ |子ID |子名 | |-------|---------| | 1 |英语 | |-------|---------| | 2 |西班牙语 | |-------|---------| | 3 |韩语 | |________|_________| + 学生 ______________________________________ |学生 |学生姓名 |性别 |子ID | |---------|---------|--------|--------| | 1 |大卫 |中号 | 1,2 | |---------|---------|--------|--------| | 2 |露西 | F | 2,3 | |_________|_________|________|________|

我想查询结果为:

____________________________________ |子ID |子名 |女 |男 | |--------|---------|--------|------| | 1 |英语 | 0 | 1 | |--------|---------|--------|------| | 2 |西班牙语 | 1 | 1 | |--------|---------|--------|------| | 3 |韩语 | 1 | 0 | |________|_________|________|______|


这是我的查询:

选择 子 ID、子名称、0 作为女性、0 作为男性 从主题

我不知道用实际计数代替 0。

【问题讨论】:

  • 你应该改变你的桌子设计。切勿在单个列中存储多个值!
  • 我知道,但是我的项目已经上线了,现在我只是做报告。稍后我将重构表,谢谢。

标签: sql-server


【解决方案1】:

因为您在表中存储 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;

Demo

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

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

我们可以更进一步,甚至将元数据与StuIDSubID 关系分开存储。但即使只使用上述方法也可以避免丑陋的连接条件。

【讨论】:

  • 我知道,但是我的项目已经上线了,现在我只是做报告。稍后我将重构表,谢谢。
  • 有时我们不得不忍受其他人糟糕的设计决策。至少您有一个改进方法的想法。
【解决方案2】:

如果您的 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
*/

【讨论】:

  • 谢谢,不过我用的是SQL Server 2014,没有STRING_SPLIT函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多