Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Модифицировать запрос без DISTINCT  [new]
nikopol
Member

Откуда:
Сообщений: 335
есть таблица некоторых объектов с ИД и кучей полей не имеющих значения к сути вопроса:
ID
---
1
2
3
4

и т.д.
Назовем ее Analit

есть таблица прав доступа к этим объектам:
ID         IDUserGroup
---------- --------------------------
1          user1
1          user2
1          group1
1          group2
2          group2
2          user2
2          user1
4          group2

Назовем ее AccesRights, права могут выдать как лично пользователю так и группам в которые этот пользователь также может входить


И есть таблица описывающая права пользователя с учетом замещений и его вхождений в группы
IDUser          IDUserGroup
--------------- ----------------------
user1           user1
user1           group1
user1           group2
user1           user2
user2           user2
user2           group1

назовем ее FullAccessRights
например user1 входит в обе группы и замещает user2. а user2 входит только в 1 группу и никого не замещает

Нужен запрос который каждому пользователю покажет только те записи из таблицы Analit, на которые у него есть права или у группы в которые он входит или если он замещает кого-то у кого есть права. У меня есть 2 варианта этого запроса.
1.
select Analit.* 
from Analit,
AccessRights,
FullAccessRights
where
AccessRights.ID = Analit.ID and
AccessRights.IDUserGroup = FullAccessRights.IDUserGroup and
FullAccessRights.IDUser = user1

так как юзер может замещять многих пользователей и входить в разные группы то в запрос надо добавить условие DISTINCT чтобы не тянулись дубли.
Вот в этом загвоздка, добавить его нельзя, так как это часть ПО и залезть в эту часть запроса нельзя. Можно только модифицировать select, from, where части, но некая "макушка" select остается недоступной к изменению в чаcтности нельзя дописать distinct. Можно ли както переписать запрос без distinct так чтобы результат был как с ним?

2. этот вариант запроса делает то что надо, но работает в разы медленее первого
select Analit.* 
from Analit
where
exists(
select 1
from
AccessRights,
FullAccessRights
where
AccessRights.ID = Analit.ID and
AccessRights.IDUserGroup = FullAccessRights.IDUserGroup and
FullAccessRights.IDUser = user1)


Я брошу все и войду в твое положение
26 сен 14, 17:15    [16627263]     Ответить | Цитировать Сообщить модератору
 Re: Модифицировать запрос без DISTINCT  [new]
invm
Member

Откуда: Москва
Сообщений: 9400
1. Заведите индексирпованное представление:
create view dbo.vEffectiveAccessRights
with schemabinding
as
select
 ar.ID, far.IDUser, count_big(*)
from
 FullAccessRights far join
 AccessRights ar on ar.IDUserGroup = far.IDUserGroup
group by
 ar.ID, far.IDUser;
go

create unique clustered index UIX_vEffectiveAccessRights__ID__IDUser on dbo.vEffectiveAccessRights (ID, IDUser);
go

2. Перепишите проблемные запрос:
select Analit.* 
from Analit
where
exists(
 select
  1
 from
  dbo.vEffectiveAccessRights with (noexpand)
 where
  ID = Analit.ID and IDUser = @user)
26 сен 14, 17:44    [16627388]     Ответить | Цитировать Сообщить модератору
 Re: Модифицировать запрос без DISTINCT  [new]
sander1
Member

Откуда: Москва
Сообщений: 366
Такой еще вариант для вас. Разбить запрос на две части, и объединить их через union. Первая - для вывода прав, которые получаются через группу, вторая - для вывода прав которые назначаются непосредственно пользователям. Это кажется немного упростит логику каждого из этих двух запросов; и кроме того, если вы объедините их через union (не union all, а union), это сгруппирует результат и уберет повторы.

p.s. И переходите, пожалуйста, с перечисления таблиц через запятую, на использование синтаксиса с join. :)
26 сен 14, 17:59    [16627452]     Ответить | Цитировать Сообщить модератору
 Re: Модифицировать запрос без DISTINCT  [new]
nikopol
Member

Откуда:
Сообщений: 335
invm,
это действительно ускорит его? сильно? разница между запросами 1 и 2 сейчас это 0 сек и 4 сек соответственно. и это на 20 000 записей
26 сен 14, 18:30    [16627542]     Ответить | Цитировать Сообщить модератору
 Re: Модифицировать запрос без DISTINCT  [new]
nikopol
Member

Откуда:
Сообщений: 335
sander1
Такой еще вариант для вас. Разбить запрос на две части, и объединить их через union. Первая - для вывода прав, которые получаются через группу, вторая - для вывода прав которые назначаются непосредственно пользователям. Это кажется немного упростит логику каждого из этих двух запросов; и кроме того, если вы объедините их через union (не union all, а union), это сгруппирует результат и уберет повторы.

p.s. И переходите, пожалуйста, с перечисления таблиц через запятую, на использование синтаксиса с join. :)

к сожалению разбить нельзя, только модификация select, where, from частей с некой фиксированный шапкой в select

з.ы. запятые это да)
26 сен 14, 18:32    [16627547]     Ответить | Цитировать Сообщить модератору
 Re: Модифицировать запрос без DISTINCT  [new]
SERG1257
Member

Откуда:
Сообщений: 2748
nikopol
этот вариант запроса делает то что надо, но работает в разы медленее первого
Курите план. Ищите отличия от первого запроса.
26 сен 14, 18:59    [16627653]     Ответить | Цитировать Сообщить модератору
 Re: Модифицировать запрос без DISTINCT  [new]
nikopol
Member

Откуда:
Сообщений: 335
SERG1257
nikopol
этот вариант запроса делает то что надо, но работает в разы медленее первого
Курите план. Ищите отличия от первого запроса.

ну так вроде всегда подзапросы будут медленнее? этож на каждую запись еще 1 запрос выполняется.
26 сен 14, 20:49    [16627933]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить