Как преобразовать несколько строк в одну строку в SQL Server?
У меня проблема с запросом. Допустим, у меня есть две таблицы с именем PersonInfo
а также PersonEducation
, Я применил операцию объединения к этим таблицам с StudentId
и у меня есть такой результат.
StudentIdId Name University Department Status
---------------------------------------------------------------
1 John Cambridge Computer Graduated
1 John Berkeley Mathematic Graduated
1 John Boston Economy Ongoing
Это всего лишь один пример ученика (Джон). Это показывает, что Джон окончил 2 университета и все еще учится в одном университете. Номера университетов могут меняться в зависимости от студентов. Мой вопрос заключается в том, как я могу показать эти 3 строки только в 1 строке. Я хочу показать всю информацию об образовании в одном ряду, чтобы не было нескольких рядов для одного человека.
Заранее спасибо за помощь.
2 ответа
Тестовые данные
DECLARE @TABLE TABLE (StudentIdId INT, Name VARCHAR(100), University VARCHAR(100)
, Department VARCHAR(100),[Status] VARCHAR(100))
INSERT INTO @TABLE VALUES
(1 ,'John','Cambridge','Computer' ,'Graduated'),
(1 ,'John','Berkeley' ,'Mathematic','Graduated'),
(1 ,'John','Boston' ,'Economy' ,'Ongoing'),
(2 ,'Pete','Cambridge','Computer' ,'Graduated'),
(2 ,'Pete','Berkeley' ,'Mathematic','Graduated')
запрос
SELECT t.StudentIdId
,t.Name
,STUFF((SELECT ', ' + University
FROM @TABLE
WHERE StudentIdId = t.StudentIdId
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,'') AS University
,STUFF((SELECT ', ' + Department
FROM @TABLE
WHERE StudentIdId = t.StudentIdId
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,'') AS Department
,STUFF((SELECT ', ' + [Status]
FROM @TABLE
WHERE StudentIdId = t.StudentIdId
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,'') AS [Status]
FROM @TABLE t
GROUP BY t.StudentIdId ,t.Name
Результат
╔═════════════╦══════╦═════════════════════════════╦═══════════════════════════════╦═══════════════════════════════╗
║ StudentIdId ║ Name ║ University ║ Department ║ Status ║
╠═════════════╬══════╬═════════════════════════════╬═══════════════════════════════╬═══════════════════════════════╣
║ 1 ║ John ║ Cambridge, Berkeley, Boston ║ Computer, Mathematic, Economy ║ Graduated, Graduated, Ongoing ║
║ 2 ║ Pete ║ Cambridge, Berkeley ║ Computer, Mathematic ║ Graduated, Graduated ║
╚═════════════╩══════╩═════════════════════════════╩═══════════════════════════════╩═══════════════════════════════╝
Это зависит от того, что вы хотите для вывода.
- Если вы хотите объединить данные в PersonEducation для подсчета статусов, то вы можете присоединиться к подзапросу таблицы PersonEducation. Есть множество статей о том, как использовать подзапросы и как группировать по полям.
Что-то вроде:
SELECT pere.StudentId
, pere.StudentName
, peri.UniversityCount
, peri.GraduatedStatusCout
, peri.OngoingStatusCount
FROM PersonInfo peri
LEFT JOIN
(SELECT StudentId
, UniversityCount = COUNT(*)
, GraduatedStatusCount = SUM(IIF(Status = 'Graduated', 1, 0))
, OngoingStatusCount = SUM(IIF(Status = 'Ongoing', 1, 0))
FROM PersonEducation
GROUP BY StudentId) pere
ON peri.StudentId = pere.StudentId;
Если вы хотите, чтобы последний университет посещал, то вам нужно какое-то поле для посещения даты. Возможно, есть несколько университетов, в которых кто-то учится одновременно, поэтому вам понадобятся правила выбора победителя. В этих случаях, однако, вы могли бы избежать использования ROW_NUMBER() в предложении OVER() для упорядочения данных и фильтрации результатов.
Вы можете объединить данные вместе, как описано здесь или в любом количестве других статей.