我有一张桌子[CourseMaster]
喜欢
CourseId CourseName
-----------------------
01 ABC
02 DEF
03 GHI
04 JKL
05 MNO
06 PQR
07 STU
Run Code Online (Sandbox Code Playgroud)
我还有一张[StudentMaster]
学生详细信息表,比如
ROLLNO NAME ADDRESS Course
------------------------------------------------
12345 RAM RAM ADDRESS 01,02,06
25695 HARI HARI ADDRESS 02,06
89685 JEFF JEFF ADDRESS 03,05,06,07
47896 DAISY DAISY ADDRESS 03
Run Code Online (Sandbox Code Playgroud)
在这里,我想使用CourseName
(Not CourseId
)获取学生详细信息。
如果中的值Course
不是逗号分隔的,那么query
使用 join 获取详细信息将非常简单。
据我所知,我可以queries
为我想要的相同结果运行两个查询,一个查询用于从[StudentMaster]
前端获取学生的详细信息。另一个用于仅通过相应的循环获取CourseName
from 。[CourseMaster]
CourseId
但事实上我只想要一个结果,query
而不是queries
为这个小任务写两个。
我想这是100%可能的。我的预期结果如下:
ROLLNO NAME ADDRESS Course
-------------------------------------------
12345 RAM RAM ADDRESS ABC,DEF,PQR
25695 HARI HARI ADDRESS DEF,PQR
89685 JEFF JEFF ADDRESS GHI,MNO,PQR,STU
47896 DAISY DAISY ADDRESS GHI
Run Code Online (Sandbox Code Playgroud)
谢谢你,任何宝贵的建议将不胜感激。
你真的应该有一个学生正在学习的课程的连接表,而不是将逗号分隔的值塞进一个元组中。如果您认为这是由于这种次优设计而导致的最后一个问题,那么您将大吃一惊。你真的应该让这个项目的所有者阅读规范化 - 是的,改变你的模式很痛苦,但不断处理保持原样的限制也是如此。
无论如何,话虽如此,您需要一个拆分功能。由于您的逗号分隔值是数字,因此您可以使用我的 XML 函数的变体;在这篇博文中还有其他几个可供选择。
CREATE FUNCTION dbo.SplitStrings_XML
(
@List VARCHAR(MAX),
@Delimiter CHAR(1) = ','
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT Item = y.i.value('(./text())[1]', 'varchar(8000)')
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
);
Run Code Online (Sandbox Code Playgroud)
现在,您的查询是:
;WITH x AS
(
SELECT s.ROLLNO, s.Name, s.Address, c.CourseId, c.CourseName
FROM dbo.StudentMaster AS s
CROSS APPLY dbo.SplitStrings_XML(s.Course, default) AS f
INNER JOIN dbo.CourseMaster AS c
ON f.item = c.CourseId
)
SELECT ROLLNO, Name, Address, STUFF((
SELECT ',' + CourseName FROM x AS x2
WHERE x2.ROLLNO = x.ROLLNO
ORDER BY CourseId FOR XML PATH,
TYPE).value(N'.[1]',N'varchar(max)'), 1, 1, '')
FROM x
GROUP BY ROLLNO, Name, Address;
Run Code Online (Sandbox Code Playgroud)
同样,这是一个复杂的解决方案,并且由于您的数据库结构较差,您必须执行的下一个查询将同样复杂和繁琐。几乎所有关于该主题的博客、文章或书籍都反对这种类型的设计,这是有原因的……
相同的溶液,当涉及到在连接建立逗号分隔值,但有一点不同亚伦贝特朗提供的一个CourseMaster.CourseId
与所述的值StudentMaster.Course
。
MS SQL Server 2014 架构设置:
create table dbo.CourseMaster
(
CourseId char(2),
CourseName char(3)
);
create table dbo.StudentMaster
(
ROLLNO char(5),
NAME varchar(10),
ADDRESS varchar(20),
Course varchar(100)
);
insert into dbo.CourseMaster values
('01', 'ABC'),
('02', 'DEF'),
('03', 'GHI'),
('04', 'JKL'),
('05', 'MNO'),
('06', 'PQR'),
('07', 'STU');
insert into dbo.StudentMaster values
('12345', 'RAM', 'RAM ADDRESS', '01,02,06'),
('25695', 'HARI', 'HARI ADDRESS', '02,06'),
('89685', 'JEFF', 'JEFF ADDRESS', '03,05,06,07'),
('47896', 'DAISY', 'DAISY ADDRESS', '03');
Run Code Online (Sandbox Code Playgroud)
查询 1:
select SM.ROLLNO,
SM.NAME,
SM.ADDRESS,
(
select ','+CM.CourseName
from dbo.CourseMaster as CM
where ','+SM.Course+',' like '%,'+CM.CourseId+',%'
for xml path(''), type
).value('substring(text()[1], 2)', 'varchar(max)') as Course
from dbo.StudentMaster as SM;
Run Code Online (Sandbox Code Playgroud)
结果:
create table dbo.CourseMaster
(
CourseId char(2),
CourseName char(3)
);
create table dbo.StudentMaster
(
ROLLNO char(5),
NAME varchar(10),
ADDRESS varchar(20),
Course varchar(100)
);
insert into dbo.CourseMaster values
('01', 'ABC'),
('02', 'DEF'),
('03', 'GHI'),
('04', 'JKL'),
('05', 'MNO'),
('06', 'PQR'),
('07', 'STU');
insert into dbo.StudentMaster values
('12345', 'RAM', 'RAM ADDRESS', '01,02,06'),
('25695', 'HARI', 'HARI ADDRESS', '02,06'),
('89685', 'JEFF', 'JEFF ADDRESS', '03,05,06,07'),
('47896', 'DAISY', 'DAISY ADDRESS', '03');
Run Code Online (Sandbox Code Playgroud)