如何在mssql中按逗号分隔的列进行分组?
我有两张桌子 T1user如何在mssql中按逗号分隔的列进行分组?,sql,sql-server,Sql,Sql Server,我有两张桌子 T1user Id Name CourseIds 1 Joel 1,2,3 2 Jeff 2,3,4 t2课程 CourseId CourseName 1 C# 2 Javascript 3 SQL 4 VB 我必须将这两个表连接起来,找出每个课程的数量——由一个用户组通过like学习 结果表 Courses Count C# 1 Javascript
Id Name CourseIds
1 Joel 1,2,3
2 Jeff 2,3,4
t2课程
CourseId CourseName
1 C#
2 Javascript
3 SQL
4 VB
我必须将这两个表连接起来,找出每个课程的数量——由一个用户组通过like学习
结果表
Courses Count
C# 1
Javascript 2
SQL 2
VB 1
我试过回答这个问题,但都没用。请帮助我。首先,您应该修复数据结构。将ID列表存储在逗号分隔的列表中是不好的,原因有很多: 将数字存储为字符串是不好的。 在单个字段中存储多个值是错误的。 不能声明外键关系是不好的。 这样的列表不能利用索引。 连接表是一个更好的选择。 有时我们会被其他人的错误决定所困扰。在这种情况下,您可以随心所欲,但效率不高:
select c.coursename,
(select count(*)
from user u
where ',' + u.courseids + ',' like '%,' + cast(c.id as varchar(255)) + ',%'
) as cnt
from courses c;
但实际上,与其将神秘的字符串操作放在一起,不如修复数据结构。首先,您应该修复数据结构。将ID列表存储在逗号分隔的列表中是不好的,原因有很多:
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;
将数字存储为字符串是不好的。
在单个字段中存储多个值是错误的。
不能声明外键关系是不好的。
这样的列表不能利用索引。
连接表是一个更好的选择。
有时我们会被其他人的错误决定所困扰。在这种情况下,您可以随心所欲,但效率不高:
select c.coursename,
(select count(*)
from user u
where ',' + u.courseids + ',' like '%,' + cast(c.id as varchar(255)) + ',%'
) as cnt
from courses c;
但实际上,与其将神秘的字符串操作放在一起,不如修复数据结构。回答得晚,但您也可以这样继续
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;
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
回答晚了,但你也可以这样继续
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
可能首先要正确地重新规范化数据库,使每个项都位于自己的行中。然后,这个查询和许多其他查询将变得微不足道。可能首先要正确地重新规范化数据库,使每个项都位于自己的行中。我已经尝试过上面的方法,但是它给出了C-1、Javascript-2、SQL-1、VB-0。有什么我想改变的吗??不像我的结果集。@Prashanth。它在SQLFiddle中工作得很好:。我已经尝试了上面的方法,但它给出了C-1、Javascript-2、SQL-1、VB-0。有什么我想改变的吗??不像我的结果集。@Prashanth。它在SQL Fiddle中运行良好:。@prasanth您可以查看answer@prasanth你能看看答案吗