如何在mssql中按逗号分隔列进行分组?

时间:2015-12-22 13:31:02

标签: sql sql-server

我有

的表格

T1(用户)

Id  Name CourseIds

1   Joel  1,2,3 
2   Jeff  2,3,4

T2(课程)

CourseId CourseName

1         C# 
2         Javascript
3         SQL
4         VB

我必须加入这两个表并找出每个课程的数量 - 由用户(分组)学习 (结果表)

Courses      Count

C#           1  
Javascript   2
SQL          2
VB           1 

我尝试过与问题相关的stackoverflow答案,但他们没有帮助。请帮帮我。

3 个答案:

答案 0 :(得分:3)

首先,您应该修复数据结构。在逗号分隔列表中存储id列表很糟糕,原因有很多:

  • 将数字存储为字符串很糟糕。
  • 在单个字段中存储多个值很糟糕。
  • 无法声明外键关系是不好的。
  • 此类列表无法利用索引。
  • 交汇处表是一个更好的选择。

有时我们会遇到其他人真正糟糕的决定。如果是这种情况,你可以做你想做的事,虽然效率不高:

select c.coursename,
       (select count(*)
        from user u
        where ',' + u.courseids + ',' like '%,' + cast(c.id as varchar(255)) + ',%'
       ) as cnt
from courses c;

但实际上,不是将神秘的字符串操作放在一起,而是最好修复数据结构。

答案 1 :(得分:1)

With cte(courseids,si,ei)
As(
 Select courseids,
              1,
             charindex(',', courseids)
   From user

Union all

Select courseids,
            Cast( 1 +ei as int),
            Charindex(',',courseids,1+ei)
From cte 
Where ei >0
)
Select substring(courseids,si, case when ei>0 then ei- si else Len(courseids) end) as courseid into #t 
From cte;

Select count(1) as count, (select coursename from courses where courseid = t.courseid) as courses
From #t t
Group by courseid;
Drop table #t;

答案 2 :(得分:1)

迟到回答,但你也可以这样继续

     DECLARE @Table1 TABLE 
    (Id int, Name varchar(4), CourseIds varchar(5))
;

INSERT INTO @Table1
    (Id, Name, CourseIds)
VALUES
    (1, 'Joel', '1,2,3'),
    (2, 'Jeff', '2,3,4')
;

DECLARE @Table2 TABLE 
    (CourseId int, CourseName varchar(10))
;

INSERT INTO @Table2
    (CourseId, CourseName)
VALUES
    (1, 'C#'),
    (2, 'Javascript'),
    (3, 'SQL'),
    (4, 'VB')
;


declare @str varchar(max)

;with cte as (
SELECT    Id,Name,
     Split.a.value('.', 'VARCHAR(100)') AS Courseid  
 FROM  (SELECT  Id,Name, 
         CAST ('<M>' + REPLACE([CourseIds], ',', '</M><M>') + '</M>' AS XML) AS String  
     FROM  @Table1) AS A CROSS APPLY String.nodes ('/M') AS Split(a))

     select TT.CourseName,COUNT(C.Courseid) AS Courseid from cte C
     INNER JOIN @Table2 TT
     ON TT.CourseId = C.Courseid
     GROUP BY TT.CourseName