Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Where all in - где все строки есть в подзапросе / 13 сообщений из 13, страница 1 из 1
24.10.2019, 17:50
    #39881139
Alex_BBB
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
Добрый день, помогите пожалуйста с запросом.

Есть:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
-- роли
DECLARE @Roles TABLE
(
  Id int, 
  Title nvarchar(10)
)

-- шаблоны назначения ролей
-- в шаблоне может быть несколько ролей
DECLARE @RoleTemplates TABLE
(
  Id int, 
  Title nvarchar(10)
)

-- Template многие_ко_многим Role
DECLARE @RoleTemplateToRole TABLE
(
	TemplateId int,
	RoleId int
)


-- таблица назначения ролей
-- Principal многие_ко_многим Role 
DECLARE @RoleAssigments TABLE
(
   PrincipalId int,
   RoleId int
)



Нужно получить шаблоны для Principal-ов.
Если у Principal есть все роли шаблона, то считаем что у Principal есть шаблон.
В идеале вот такая View нужна
Код: sql
1.
2.
PrincipalId int
TemplateId int



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
insert into @Roles values (1, 'Role1')
insert into @Roles values (2, 'Role2')
insert into @Roles values (3, 'Role3')

insert into @RoleTemplates values (1, 'Template1')

insert into @RoleTemplateToRole values (1, 1)
insert into @RoleTemplateToRole values (1, 2)


insert into @RoleAssigments values (1, 1)
insert into @RoleAssigments values (1, 2)
insert into @RoleAssigments values (1, 3)

insert into @RoleAssigments values (2, 1)
insert into @RoleAssigments values (2, 3)


-- это не правильный запрос для примера
select 
	ass.PrincipalID,
	ass.RoleID,
	templToRole.TemplateId
from @RoleAssigments ass
join @RoleTemplateToRole templToRole ON ass.RoleID = templToRole.RoleId
...
Рейтинг: 0 / 0
24.10.2019, 18:04
    #39881151
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
Alex_BBBЕсли у Principal есть все роли шаблона, то считаем что у Principal есть шаблон.
реляционное деление (?)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select 
	ass.PrincipalID,
	templToRole.TemplateId
from @RoleAssigments ass
join @RoleTemplateToRole templToRole ON ass.RoleID = templToRole.RoleId
group by
	ass.PrincipalID,
	templToRole.TemplateId
having count(distinct ass.RoleID) = (select count(*) from @RoleTemplateToRole xz where xz.TemplateId = templToRole.TemplateId)
...
Рейтинг: 0 / 0
24.10.2019, 18:30
    #39881178
Alex_BBB
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
court, спасибо! Похоже оно самое
...
Рейтинг: 0 / 0
25.10.2019, 05:43
    #39881295
aleks222
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
courtAlex_BBBЕсли у Principal есть все роли шаблона, то считаем что у Principal есть шаблон.
реляционное деление (?)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select 
	ass.PrincipalID,
	templToRole.TemplateId
from @RoleAssigments ass
join @RoleTemplateToRole templToRole ON ass.RoleID = templToRole.RoleId
group by
	ass.PrincipalID,
	templToRole.TemplateId
having count(distinct ass.RoleID) = (select count(*) from @RoleTemplateToRole xz where xz.TemplateId = templToRole.TemplateId)



Ужос. Иди выучи, наконец, exists.

ЗЫ. "есть все роли шаблона" = нет ролей, которых нет
...
Рейтинг: 0 / 0
25.10.2019, 09:45
    #39881344
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
aleks222courtпропущено...

реляционное деление (?)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select 
	ass.PrincipalID,
	templToRole.TemplateId
from @RoleAssigments ass
join @RoleTemplateToRole templToRole ON ass.RoleID = templToRole.RoleId
group by
	ass.PrincipalID,
	templToRole.TemplateId
having count(distinct ass.RoleID) = (select count(*) from @RoleTemplateToRole xz where xz.TemplateId = templToRole.TemplateId)




Ужос. Иди выучи, наконец, exists.

ЗЫ. "есть все роли шаблона" = нет ролей, которых нетну так "изобрази"
Потом "померяемся" :)
...
Рейтинг: 0 / 0
25.10.2019, 09:46
    #39881347
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
Alex_BBB,

так ещё можно. Может лучше будет ...
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
;with cte as 
	(select *, count(*)over(partition by TemplateId) as cntAll from @RoleTemplateToRole)
select 
	ass.PrincipalID,
	templToRole.TemplateId
from @RoleAssigments ass
join cte templToRole ON ass.RoleID = templToRole.RoleId
group by
	ass.PrincipalID,
	templToRole.TemplateId,
	templToRole.cntAll
having count(*) = templToRole.cntAll
...
Рейтинг: 0 / 0
25.10.2019, 09:55
    #39881353
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
...
Рейтинг: 0 / 0
25.10.2019, 10:06
    #39881363
Minamoto
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
courtaleks222пропущено...


Ужос. Иди выучи, наконец, exists.

ЗЫ. "есть все роли шаблона" = нет ролей, которых нетну так "изобрази"
Потом "померяемся" :) Не хватает таблички

Код: sql
1.
2.
DECLARE @Principals table (PrincipalId int)
INSERT INTO @Principals (PrincipalId) VALUES (1), (2)



Запрос будет такой:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
SELECT  
    * 
FROM    
    @Principals p
    INNER JOIN 
        @RoleTemplates t
            ON NOT EXISTS (
                SELECT 
                    * 
                FROM 
                    @RoleTemplateToRole tr 
                    LEFT JOIN 
                        @RoleAssigments ra 
                            ON ra.PrincipalId = p.PrincipalId 
                            AND ra.RoleId = tr.RoleId
                WHERE tr.TemplateId = t.Id
                    AND ra.RoleId IS NULL)



Померять было бы неплохо, потому что я не уверен, что это будет быстрее, но на этих данных все по 0, нужно либо на реальных данных смотреть, либо нагенерить побольше вариантов.
...
Рейтинг: 0 / 0
25.10.2019, 12:19
    #39881480
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
...
Рейтинг: 0 / 0
25.10.2019, 12:25
    #39881491
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
Minamotocourtпропущено...
ну так "изобрази"
Потом "померяемся" :) Не хватает таблички

Код: sql
1.
2.
DECLARE @Principals table (PrincipalId int)
INSERT INTO @Principals (PrincipalId) VALUES (1), (2)




Запрос будет такой:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
SELECT  
    * 
FROM    
    @Principals p
    INNER JOIN 
        @RoleTemplates t
            ON NOT EXISTS (
                SELECT 
                    * 
                FROM 
                    @RoleTemplateToRole tr 
                    LEFT JOIN 
                        @RoleAssigments ra 
                            ON ra.PrincipalId = p.PrincipalId 
                            AND ra.RoleId = tr.RoleId
                WHERE tr.TemplateId = t.Id
                    AND ra.RoleId IS NULL)




Померять было бы неплохо, потому что я не уверен, что это будет быстрее, но на этих данных все по 0, нужно либо на реальных данных смотреть, либо нагенерить побольше вариантов.как минимум стоимость запроса, для вашего, у меня "пишет" в 3-и раза меньше чем моего ...

пс
но, кстате, эти запросы, совершенно по разному будут "реагировать" на "пустой" шаблон
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
-- роли
DECLARE @Roles TABLE
(
  Id int, 
  Title nvarchar(10)
)

-- шаблоны назначения ролей
-- в шаблоне может быть несколько ролей
DECLARE @RoleTemplates TABLE
(
  Id int, 
  Title nvarchar(10)
)

-- Template многие_ко_многим Role
DECLARE @RoleTemplateToRole TABLE
(
	TemplateId int,
	RoleId int
)


-- таблица назначения ролей
-- Principal многие_ко_многим Role 
DECLARE @RoleAssigments TABLE
(
   PrincipalId int,
   RoleId int
)
DECLARE @Principals table (PrincipalId int)
INSERT INTO @Principals (PrincipalId) VALUES (1), (2)


insert into @Roles values (1, 'Role1')
insert into @Roles values (2, 'Role2')
insert into @Roles values (3, 'Role3')

insert into @RoleTemplates values (1, 'Template1')

--insert into @RoleTemplateToRole values (1, 1)
--insert into @RoleTemplateToRole values (1, 2)
--insert into @RoleTemplateToRole values (1, 4)


insert into @RoleAssigments values (1, 1)
insert into @RoleAssigments values (1, 2)
insert into @RoleAssigments values (1, 3)
insert into @RoleAssigments values (1, 4)

insert into @RoleAssigments values (2, 1)
insert into @RoleAssigments values (2, 2)
insert into @RoleAssigments values (2, 3)

--	***	1	
select 
	ass.PrincipalID,
	templToRole.TemplateId
from @RoleAssigments ass
join @RoleTemplateToRole templToRole ON ass.RoleID = templToRole.RoleId
group by
	ass.PrincipalID,
	templToRole.TemplateId
having count(*) = (select count(*) from @RoleTemplateToRole xz where xz.TemplateId = templToRole.TemplateId)

--	***	2	
SELECT  
    * 
FROM    
    @Principals p
    INNER JOIN 
        @RoleTemplates t
            ON NOT EXISTS (
                SELECT 
                    * 
                FROM 
                    @RoleTemplateToRole tr 
                    LEFT JOIN 
                        @RoleAssigments ra 
                            ON ra.PrincipalId = p.PrincipalId 
                            AND ra.RoleId = tr.RoleId
                WHERE tr.TemplateId = t.Id
                    AND ra.RoleId IS NULL)

...
Рейтинг: 0 / 0
25.10.2019, 12:26
    #39881495
court
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
courtпс
но, кстате, эти запросы, совершенно по разному будут "реагировать" на "пустой" шаблон
-- *** 1
PrincipalIDTemplateId

-- *** 2
PrincipalIdIdTitle11Template121Template1
...
Рейтинг: 0 / 0
25.10.2019, 12:59
    #39881516
Minamoto
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
courtно, кстате, эти запросы, совершенно по разному будут "реагировать" на "пустой" шаблон

Да, и это скорее в пользу решения с группировкой, т.к., по идее, фраза "Если у Principal есть все роли шаблона, то считаем что у Principal есть шаблон.", подразумевает, что у шаблона есть роли. Но в мой запрос тоже несложно добавить это условие - через ещё один exists, например.
...
Рейтинг: 0 / 0
25.10.2019, 13:07
    #39881519
iap
iap
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Where all in - где все строки есть в подзапросе
courtiapВот, мы как-то обсуждали: Как реализовать операцию реляционной алгебры "деление" на SQL?
вот тут ещё "было интересно" - запрос реляционное деление Чего мелочиться?

YouTube Video
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Where all in - где все строки есть в подзапросе / 13 сообщений из 13, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]