Оптимизированный запрос, чтобы получить мин / макс - PullRequest
2 голосов
/ 09 августа 2010

У меня есть данные как

Сотрудник:

id  Name
--------
1   xyz
2   abc
3   qaz

Employee_A: (Eid - таблица сотрудников, title - title title)

eid    active    type    title
------------------------------
1     1         1        1
1     1         2        2
1     1         4        3
2     0         3        4
2     1         2        2
2     0         6        5
3     0         1        1
3     0         6        5
3     0         4        3

Title:

id  rank title_name
--------------------
1   1     Manager
2   1     Asst Manager
3   2     Staff1
4   3     Staff2
5   4     Staff3

Мой запрос выглядит как

SELECT name, t.title_name
FROM Employee e
INNER JOIN Employee_A a ON e.id = a.eid
INNER JOIN title t on a.title = t.id
WHERE a.type in (1,2) and active = 1
and t.rank = /* step 1 */
(select min(rank) FROM Employee_A a1 INNER JOIN title t1 ON a1.title = t1.id 
 WHERE a1.type in (1,2) and active = 1 AND a1.eid = e.id)
AND a.type = /* step 2 */
    ( select min(type) FROM Employee_A a2 INNER JOIN title t2 on a2.title = t2.id
      WHERE a2.type in (1,2) and active = 1 and a2.eid = e.id
     and t2.rank = 
         (select min(rank) FROM Employee_A a3 INNER JOIN title t3 ON a3.title = t3.id 
          WHERE a3.type in (1,2) and active = 1 AND a3.eid = e.id)
    )

У меня более 400К записей, и я пытаюсь запросить минимальный тип с минимальным рангом (2 заголовка имеют одинаковый ранг, поэтому необходимо выбрать минимальный заголовокмежду ними).Мой запрос занимает больше времени, и я хочу его оптимизировать. Можно ли как-то избежать шагов 1, 2 и сделать это проще и быстрее?

Вывод:

Name   title_name
-----------------
xyz    Manager
abc    Asst Manager

Ответы [ 2 ]

3 голосов
/ 09 августа 2010

Делает ли это то, что вам нужно?

;WITH cte AS
(
SELECT name, t.title_name, 
  row_number() over (partition by e.id order by rank, type) rn
FROM Employee e
INNER JOIN Employee_A a ON e.id = a.eid
INNER JOIN title t on a.title = t.id
WHERE a.type in (1,2) and active = 1
)

select name,  title_name from cte
where rn=1

Или другая альтернатива

SELECT e.name, t.title_name
FROM Employee e 
CROSS APPLY 
(
SELECT TOP (1) title_name 
FROM Employee_A a 
INNER JOIN title t on a.title = t.id
WHERE a.type in (1,2) and active = 1 AND e.id = a.eid
order by rank, type
) t
3 голосов
/ 09 августа 2010

Возможно, я слишком упрощен, но попробуй:

select emp.name, MIN(a.title), MIN(t.rank)
from Employee emp
join Employee_A a on emp.id = a.eid
                  AND a.type in(1,2)
                  and a.active = 1
join title t on a.title = t.id
where not exists (select 1 from Employee_A where eid = emp.id and title < a.title and active = 1)
group by emp.name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...