如何将3个表中的多行组合成一行

时间:2016-04-28 15:06:04

标签: sql-server ssms-2012

我有3张看起来像这样的表:

表A
学生ID |课程名称|课程部分
1 |英语| A
1 |数学|乙
2 |化学| C
2 |历史| A

表B
课程名称|课程部分|教师ID |百分比
数学| B | 67890 | 50
数学| B | 54321 | 50
历史| A | 67890 | 100
英语| A | 12345 | 100
化学| C | 09876 | 100

表C
讲师ID |讲师电子邮件
09876 | instrchem@testco.us
12345 |instreng@testco.edu
54321 |instrmathalso@testco.us
67890 |instrhist@testco.edu

我希望查询的输出如下所示:

学生ID课程名称科导师电子邮件
1在线英文instreng@testco.edu
1数学乙instrhist@testco.edu; instrmath@testco.us
2化学品C instrchem@testco.us
2历史A instrhist@testco.us

我尝试使用coalesce创建表变量,以及其他一些建议,但我没有取得任何成功。任何想法都将不胜感激。

谢谢。
艾琳

3 个答案:

答案 0 :(得分:0)

您可以尝试加入这三个表

SELECT      StudentID           = [TABLE A].[Student id]
            ,[TABLE A].[Course Name]
            ,Section            = [TABLE A].[Course Section]
            ,[TABLE C].[Instructor Email]
FROM        [TABLE A]
INNER JOIN  [TABLE B]
ON          [TABLE A].[Course Name]     = [TABLE B].[Course Name]
AND         [TABLE A].[Course Section]  = [TABLE B].[Course Section]
INNER JOIN  [TABLE C]
ON          [TABLE B].[Instructor ID]   = [TABLE C].[Instructor ID]

答案 1 :(得分:0)

试试这个

    WITH    cte
          AS ( SELECT   A.Student_Id AS StudentID
                      , A.CourseName AS [Course Name]
                      , A.CourseSection AS Section
               FROM     #TableA A
                        INNER JOIN #TableB B
                        ON B.CourseName = A.CourseName
                           AND B.CourseSection = A.CourseSection
                        INNER JOIN #TableC C
                        ON B.InstructorID = C.InstuctorID
             )
    SELECT  cte.StudentID
          , cte.[Course Name]
          , cte.Section
          , STUFF((SELECT   ',' + InstructorEmail
                   FROM     #TableC c1
                            INNER JOIN #TableB b1
                            ON b1.InstructorID = c1.InstuctorID
                            INNER JOIN #TableA a1
                            ON a1.CourseName = b1.CourseName
                   WHERE    a1.Student_Id = cte.StudentID
                            AND b1.CourseName = cte.[Course Name]
                            AND a1.CourseSection = cte.Section
            FOR   XML PATH('')
                    , TYPE).value('(./text())[1]', 'varchar(max)'), 1, 1, '') AS [Instructor Email]
    FROM    cte
    GROUP BY cte.StudentID
          , cte.[Course Name]
          , cte.Section;

答案 2 :(得分:0)

您可以使用标量函数和光标来完成。

首先使用数据创建表:

CREATE TABLE dbo.Student
(
    StudentId int NOT NULL,
    CourseName nvarchar(20) NOT NULL,
    CourseSection nchar(1) NOT NULL
);

INSERT INTO dbo.Student (StudentId, CourseName, CourseSection)
    VALUES (1, N'English', N'A'),
        (1, N'Math', N'B'),
        (2, N'Chemistry', N'C'),
        (2, N'History', N'A');

CREATE TABLE dbo.Course
(
    CourseName nvarchar(20) NOT NULL,
    CourseSection nchar(1) NOT NULL,
    InstructorId int NOT NULL,
    [Percentage] int NOT NULL
);

INSERT INTO dbo.Course (CourseName, CourseSection, InstructorId, [Percentage])
    VALUES (N'Math', N'B', 67890, 50),
        (N'Math', N'B', 54321, 50),
        (N'History', N'A', 67890, 100),
        (N'English', N'A', 12345, 100),
        (N'Chemistry', N'C', 9876, 100);

CREATE TABLE dbo.Instructor
(
    InstructorId int NOT NULL,
    InstructorEmail nvarchar(50) NOT NULL
);

INSERT INTO dbo.Instructor (InstructorId, InstructorEmail)
    VALUES (09876, N'instrchem@testco.us'),
        (12345, N'instreng@testco.edu'),
        (54321, N'instrmathalso@testco.us'),
        (67890, N'instrhist@testco.edu');

然后创建一个标量函数,用于连接教师电子邮件。它使用光标来做到这一点。

CREATE FUNCTION dbo.uf_ConcatEmails
(
    @CourseName nvarchar(20),
    @CourseSection nchar(1)
)
RETURNS nvarchar(500)
AS
BEGIN
    DECLARE @e nvarchar(500) = NULL;

    DECLARE myCursor CURSOR LOCAL
        FAST_FORWARD READ_ONLY
        FOR SELECT I.InstructorEmail
            FROM dbo.Course AS C
                INNER JOIN dbo.Instructor AS I
                    ON I.InstructorId = C.InstructorId
            WHERE C.CourseName = @CourseName AND C.CourseSection = @CourseSection
            ORDER BY I.InstructorEmail;

    OPEN myCursor;
    DECLARE @email nvarchar(50);
    FETCH NEXT FROM myCursor INTO @email;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @e = IIF(@e IS NULL, @email, CONCAT(@e, N';', @email));
        FETCH NEXT FROM myCursor INTO @email;
    END

    CLOSE myCursor;
    DEALLOCATE myCursor;

    RETURN @e;
END

然后去做!

SELECT StudentId, CourseName, CourseSection, dbo.uf_ConcatEmails(CourseName, CourseSection) AS 'InstructorEmail'
    FROM dbo.Student
    ORDER BY StudentId, CourseName;

enter image description here