2016-12-20 4 views
1

Как правильно заданный запрос, так как он использует T1 внутри предложения и T1 объявляется после завершения предложения внутри WITH.Как работает следующий SQL-запрос?

WITH T1(Emp,Manager,Salary) AS 
( 
SELECT tt2.[Emp],tt2.[Manager],tt2.[Salary] 
FROM [YourTable] AS tt1 
RIGHT OUTER JOIN [YourTable] AS tt2 ON tt1.[Emp]=tt2.[Manager] 
WHERE tt1.[Emp] is NULL 
UNION ALL 
SELECT r.[Emp],T1.[Manager],r.[Salary] 
FROM [YourTable] AS r 
INNER JOIN T1 ON r.[Manager]=T1.[Emp] 
) 
SELECT [Manager],SUM([Salary]) AS Salary 
FROM T1 
GROUP BY [Manager] 
ORDER BY SUM([Salary]) DESC 

Выше запроса ответить на следующий вопрос -

У меня есть таблица со столбцами (Сотрудник, менеджер, зарплата). Необходимо рассчитать совокупную зарплату для всех сотрудников, соответствующих менеджерам верхнего уровня в одном SQL. Например

Input table is : 
Emp Manager Salary 
A T 10 
B A 11 
C F 13 
D B 5 

Результат должен быть:

Top-Lvl Manager Salary(agg) 
T 26 
F 13 

Менеджер-Работник наслоение может пойти несколько уровней.

+0

Я удалил несовместимые теги базы данных. Пожалуйста, пометьте базу данных, которую вы действительно используете. –

+1

Этот запрос был создан с использованием CTE (выражение Comman Table Expression). Для получения дополнительной информации об этом, пожалуйста, перейдите по этой ссылке: https: //www.codeproject.com/Articles/275645/CTE-In-SQL-Server – LogicalDesk

ответ

4

Это рекурсивный запрос. Часть до UNION ALL получает базовые записи. Часть после него рекурсивно получает больше строк, привязанных к первой.

Первая часть смутно написана. Это шаблон антисоединения, дополненный даже правым внешним соединением, которое многие считают трудным для чтения. Это просто означает, что это:

select emp, manager, salary 
from yourtable 
where manager not in (select emp from yourtable); 

Таким образом, вы получите все сотрудники, которые не имеют менеджера (то есть супер-менеджеры).

С деталью после UNION ALL вы получаете подчиненных и подчиненных этих и т. Д. Иерархический запрос.

В прошлом в

SELECT [Manager],SUM([Salary]) AS Salary 
FROM T1 
GROUP BY [Manager] 
ORDER BY SUM([Salary]) DESC 

вы используете эти строки, чтобы получить зарплату аккумулированной за менеджера.

Здесь вы можете прочитать рекурсивные запросы в SQL Server: https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx.

1

Внутри withT1 ссылки на INNER JOIN T1 ON r.[Manager]=T1.[Emp] которые, вероятно, являются таблицами в вашей БД. Вне withT1 ссылки на результат with заявление.

+0

Я не думаю, что это так. Нет другой таблицы с именем T1. Он использует T1, потому что ему нужно сделать это рекурсивно для одиночного расслоения для многоуровневого расслоения Manager-Employee. –

+0

Если вы уверены, что нет таблицы T1 и синонима, это означает, что ответ Торстен - это то, что работает здесь. – Kacper

2

EDIT - Less над-убить

Declare @YourTable table (Emp varchar(25),Manager varchar(25),Salary int) 
Insert into @YourTable values 
('A','T',10), 
('B','A',11), 
('C','F',13), 
('D','B',5) 

;with cteP as (
     Select Seq = cast(1000+Row_Number() over (Order by Emp) as varchar(500)) 
      ,Emp=Manager 
      ,Manager=cast(null as varchar(25)) 
      ,Lvl=1 
      ,Salary = 0 
     From @YourTable 
     Where Manager Not In (Select Distinct Emp From @YourTable) 
     Union All 
     Select Seq = cast(concat(p.Seq,'.',1000+Row_Number() over (Order by r.Emp)) as varchar(500)) 
      ,r.Emp 
      ,r.Manager 
      ,p.Lvl+1 
      ,r.Salary 
     From @YourTable r 
     Join cteP p on r.Manager = p.Emp) 
Select TopLvl = A.Emp 
     ,Salary = sum(B.Salary) 
from cteP A 
Join cteP B on (B.Seq Like A.Seq+'%') 
Where A.Lvl=1 
Group By A.Emp 

Возвращает

TopLvl Salary 
F  13 
T  26 
Смежные вопросы