SQL: один 2 много строк с множеством строк, объединенных в один столбец - PullRequest
1 голос
/ 08 февраля 2020

У меня есть четыре таблицы, а именно tblProject (одна запись), tblTeamMembers (много записей), tblProjectStatus (справочная таблица) и tblProjectScoresComments (много записей). Я использую SQL Server 2017.

Ниже приведены определения таблиц:

tblProject :

[ProjectID] [INT] IDENTITY(1,1) NOT NULL,
[ProjectName] [NVARCHAR](150) NOT NULL,
[CommunityProblem] [NTEXT] NOT NULL,
[IctSolveCommunityProblem] [NTEXT] NOT NULL,
[TeamMemberRoles] [NTEXT] NOT NULL,
[ProjectImpact] [NTEXT] NOT NULL,
[HelpRaiseFunds] [NTEXT] NOT NULL,
[ProjectStatus] [INT] NOT NULL,
[CaptureDate] [DATE] NOT NULL

tblTeamMembers :

[MemberID] [INT] IDENTITY(1,1) NOT NULL,
[Person] [NVARCHAR](150) NOT NULL,
[SalRef] [NVARCHAR](50) NOT NULL,
[Email] [NVARCHAR](150) NOT NULL,
[UserName] [NVARCHAR](150) NOT NULL,
[TeamLeader] [INT] NOT NULL,
[ProjectLeader] [INT] NOT NULL,
[ProjectLeaderContactNo] [NVARCHAR](150) NULL,
[ProjectID] [INT] NOT NULL

tblProjectScoresComments

[RecID] [INT] IDENTITY(1,1) NOT NULL,
[ProjectID] [INT] NOT NULL,
[Score] [FLOAT] NOT NULL,
[Comments] [NVARCHAR](MAX) NULL,
[UserID] [NVARCHAR](150) NOT NULL,
[DateCaptured] [DATETIME] NOT NULL

tblProjectStatus :

[ProjectStatusID] [INT] IDENTITY(1,1) NOT NULL,
[ProjectStatus] [NVARCHAR](100) NOT NULL

Я хотел бы получить результаты чтобы вернуть столбцы из всех трех таблиц, но в 3-й таблице (tblProjectScoresComments) есть много записей, а для столбца [Score] должно быть возвращено среднее значение, а в столбце [Comments] все комментарии должны быть возвращены как 1 столбец и каждый комментарий. должен быть разделен запятой (,).

Я хотел бы использовать запрос, подобный следующему:

SELECT 
    p.ProjectID, p.ProjectName AS Project, 
    ps.ProjectStatus, 
    tm.Person AS ProjectLeader, 
    p.CaptureDate, [AVERAGE_SCORE_FOR_ALL] AS Score,  
    [ALL_COMMENTS_MERGED_TO_ONE_COLUMN] AS Comments
FROM
    dbo.tblProject AS p 
INNER JOIN 
    dbo.tblProjectStatus AS ps ON p.ProjectStatus = ps.ProjectStatusID 
INNER JOIN 
    dbo.tblTeamMembers AS tm ON p.ProjectID = tm.ProjectID 
INNER JOIN 
    dbo.tblProjectScoresComments AS psc ON p.ProjectID = psc.ProjectID
WHERE
    (tm.ProjectLeader = 1)

Результаты должны выглядеть примерно так:

ProjectID | Project                                                   | ProjectStatus    | ProjectLeader | CaptureDate | Score   |Comments
---------------------------------------------------------------------------------------------------------------------------------------------------------------
1         | Access to ICT-Makatane High School and Community Project  | Not yet decided  | Mary Ndlovu   | 2019-10-04  | 1.67    |Comment 1,Comment 2,Comment 3
2         | Asample project                                           | Rejected         | Joe Soap      | 2019-11-07  | 3       |Comment 1,Comment 2

Буду очень признателен за помощь!

1 Ответ

0 голосов
/ 08 февраля 2020

Это звучит как агрегация:

SELECT p.ProjectID, p.ProjectName AS Project, ps.ProjectStatus, tm.Person AS ProjectLeader, 
p.CaptureDate,
       avg(psc.score) AS avg_score, 
       string_agg(psc.comments, ' ') as Comments
FROM dbo.tblProject p JOIN
     dbo.tblProjectStatus ps
     ON p.ProjectStatus = ps.ProjectStatusID JOIN
     dbo.tblTeamMembers tm
     ON p.ProjectID = tm.ProjectID JOIN
     dbo.tblProjectScoresComments 
     psc
     ON p.ProjectID = psc.ProjectID
WHERE tm.ProjectLeader = 1
GROUP BY p.ProjectID, p.ProjectName AS Project, ps.ProjectStatus, tm.Person AS ProjectLeader, 
p.CaptureDate;

РЕДАКТИРОВАТЬ:

Альтернатива string_agg() довольно грязная:

SELECT . . .,
       psc.avg_score, c.comments,
FROM dbo.tblProject p JOIN
     dbo.tblProjectStatus ps
     ON p.ProjectStatus = ps.ProjectStatusID JOIN
     dbo.tblTeamMembers tm
     ON p.ProjectID = tm.ProjectID OUTER APPLY
     (SELECT STUFF( (SELECT ', ' + psc.comment
                     FROM dbo.tblProjectScoresComments psc
                     WHERE p.ProjectID = psc.ProjectID
                     FOR XML PATH (''), TYPE 
                    ).value(N'.[1]', N'nvarchar(max)'
                           ), 1, 2, ''
                  ) as comments
     ) c OUTER APPLY
     (SELECT AVG(psc.score) as avg_score
      FROM dbo.tblProjectScoresComments psc
      WHERE p.ProjectID = psc.ProjectID
     ) psc 

Внешний GROUP BY следует не нужно.

...