#sql-server #string #group-by #pivot #window-functions
#sql-сервер #строка #группировать по #сводная #окно-функции
Вопрос:
У меня есть несколько таблиц SQL Server:
- Сотрудники [EmpID (pk), имя, обозначение]
- Проекты [PID (pk), EmpID (fk), PCode, PName, Dept]
Таблицы имеют отношение многие к одному, то есть один сотрудник может работать над несколькими проектами.
Я хочу показать результат таким образом, чтобы у каждого сотрудника была только одна строка, а все проекты, над которыми он работал, были показаны в разделе столбца, сгруппированном в соответствии с PCode.
Я не могу понять, как транспонировать строки в столбец, когда количество сгенерированных столбцов неизвестно.
Пример данных:
Сотрудник:
EmpId Name Designation
------------------------
001 Mat Manager
002 Ash Developer
003 Paul Analyst
Проекты:
PID EmpID PCode PName Dept
-------------------------------------
1 001 111 Project1 Sales
2 001 111 Project1.1 Retail
3 001 222 Project2 Banking
4 002 222 Project2.1 Retail
Пример вывода:
EmpID Name Project-1 Project-2 Project-3
---------------------------------------------------------------------------
001 Abc 111,Project1,Sales 111,Project1.1,Retail 222,Project2,Banking
002 Def 222,Project2.1,Retail
Комментарии:
1. предоставьте образцы данных и желаемый результат в формате таблицы
2. Обновлен вопрос. Пожалуйста, проверьте
3. какую версию sql Server вы используете
Ответ №1:
Вы можете перечислить проекты каждого сотрудника в подзапросе с помощью row_number()
, затем использовать условную агрегацию для поворота во внешнем запросе:
select e.empid, e.name,
max(case when rn = 1 then concat_ws(',', p.pcode, p.pname, p.pdept) end) project1,
max(case when rn = 2 then concat_ws(',', p.pcode, p.pname, p.pdept) end) project2,
max(case when rn = 3 then concat_ws(',', p.pcode, p.pname, p.pdept) end) project3
from employee e
inner join (
select p.*, row_number() over(partition by empid order by pid) rn
from projects p
) p on p.empid = e.empid
group by e.empid, e.name
Комментарии:
1. Это выдает мне эту ошибку «Код ошибки: 1064 У вас ошибка в вашем синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, на предмет правильного синтаксиса для использования near «(раздел по порядку empid по pid) rn
2. @user8306074: это сообщение об ошибке MySQL. Почему вы отметили свой вопрос SQL Server?
row_number()
Я доступен только в MySQL 8.0.3. У меня огромный набор данных, и я не знаю максимального количества проектов для каждого сотрудника. Итак, в этом сценарии, как я могу сгенерировать несколько столбцов проекта?
Ответ №2:
Вы можете использовать PIVOT
команду для транспонирования ваших данных. В вашем случае, который вам неизвестен, количество сгенерированных столбцов неизвестно. Вам нужно запросить, чтобы найти имя столбца сгенерированного столбца, затем вы можете объединить все имена вашего столбца с помощью PIVOT
команды, как показано ниже в инструкции запроса.
DECLARE @columnName NVARCHAR(MAX), @pivotSql NVARCHAR(MAX)
SELECT
em.EmpID,
em.Name,
pr.Pname,
pr.Pcode ',' pr.PName ',' pr.Dept Detail
INTO #temp
FROM Employee em
INNER JOIN Projects pr ON em.EmpID = pr.EmpID
SELECT
t.PName name
INTO #AllProject
FROM #temp t
GROUP BY t.PName
SET @columnName = '';
DECLARE
@projectName VARCHAR(MAX);
DECLARE cursor_allProject CURSOR
FOR SELECT
name
FROM
#AllProject;
OPEN cursor_allProject;
FETCH NEXT FROM cursor_allProject INTO @projectName;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @columnName = @columnName ', [' @projectName ']';
FETCH NEXT FROM cursor_allProject INTO @projectName;
END;
CLOSE cursor_allProject;
DEALLOCATE cursor_allProject;
SET @pivotSql = 'SELECT t.EmpID, t.Name FROM #temp t PIVOT t.Detail (FOR t.Pname IN (' @columnName ') )'
EXEC (@pivotSql)
Комментарии:
1. какую версию SQL вы используете?
2. Вы можете использовать с любым SQL Server