在 SQL Server 中使用逗号分隔值连接

Tuf*_*and 6 join sql-server

我有一张桌子[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]前端获取学生的详细信息。另一个用于仅通过相应的循环获取CourseNamefrom 。[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)

谢谢你,任何宝贵的建议将不胜感激。

Aar*_*and 8

你真的应该有一个学生正在学习的课程的连接表,而不是将逗号分隔的值塞进一个元组中。如果您认为这是由于这种次优设计而导致的最后一个问题,那么您将大吃一惊。你真的应该让这个项目的所有者阅读规范化 - 是的,改变你的模式很痛苦,但不断处理保持原样的限制也是如此。

无论如何,话虽如此,您需要一个拆分功能。由于您的逗号分隔值是数字,因此您可以使用我的 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)

同样,这是一个复杂的解决方案,并且由于您的数据库结构较差,您必须执行的下一个查询将同样复杂和繁琐。几乎所有关于该主题的博客、文章或书籍都反对这种类型的设计,这是有原因的……


Mik*_*son 5

相同的溶液,当涉及到在连接建立逗号分隔值,但有一点不同亚伦贝特朗提供的一个CourseMaster.CourseId与所述的值StudentMaster.Course

SQL小提琴

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)