Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > выборка из более чем двух таблиц


Автор: serghd 28.2.2012, 18:21
Здравствуйте, интересен следующий вопрос. Есть таблица пользователей, пользователь может иметь 6 различных уровней прав. Для каждого уровня прав - отдельная таблица (поля у них, допустим: id | user_id). Вопрос в том, можно ли как-то получить все уровни права пользователя не считывая отдельно каждую из таблиц прав, а одним запросом? Т.е. если его id есть в таблица_прав1, то по данному праву у объекта пользователя -  true. Также и с остальными таблицами прав.

Автор: Zloxa 28.2.2012, 19:40
stfg http://www.google.ru/search?rlz=1C1CHHP_ruRU415RU415&aq=f&sourceid=chrome&ie=UTF-8&q=%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5+sql#hl=ru&newwindow=1&rlz=1C1CHHP_ruRU415RU415&sclient=psy-ab&q=sql+%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&pbx=1&oq=sql+%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&aq=f&aqi=&aql=&gs_sm=3&gs_upl=17l3681l1l3975l4l4l0l0l0l2l1363l2582l5-2.0.1l3l0&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&fp=77f2849bf359a895&biw=1280&bih=915

Автор: serghd 28.2.2012, 19:46
Цитата(Zloxa @ 28.2.2012,  19:40)
stfg http://www.google.ru/search?rlz=1C1CHHP_ruRU415RU415&aq=f&sourceid=chrome&ie=UTF-8&q=%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5+sql#hl=ru&newwindow=1&rlz=1C1CHHP_ruRU415RU415&sclient=psy-ab&q=sql+%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&pbx=1&oq=sql+%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5&aq=f&aqi=&aql=&gs_sm=3&gs_upl=17l3681l1l3975l4l4l0l0l0l2l1363l2582l5-2.0.1l3l0&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&fp=77f2849bf359a895&biw=1280&bih=915

я в курсе о нём. Вы думаете, что в этом случае это поможет?)

Автор: Akina 28.2.2012, 19:59
Из описания ни хрена не удаётся понять. Кроме того, что ACL реализованы через одно место - право на объект есть одна сущность, и негоже размазывать её по куче таблиц

Цитата(serghd @  28.2.2012,  19:21 Найти цитируемый пост)
одним запросом?

+ stfw http://www.google.ru/search?rlz=1C1CHHP_ruRU415RU415&aq=f&sourceid=chrome&ie=UTF-8&q=%D0%BB%D0%B5%D0%B2%D0%BE%D0%B5+%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5+sql#sclient=psy-ab&hl=ru&newwindow=1&rlz=1C1CHHP_ruRU415RU415&source=hp&q=sql+%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5+%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2&pbx=1&oq=sql+%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5+&aq=2&aqi=g4&aql=&gs_sm=3&gs_upl=0l0l1l328l0l0l0l0l0l0l0l0ll0l0&bav=on.2,or.r_gc.r_pw.,cf.osb&fp=591c3abd986ea62a&biw=1680&bih=912

Цитата(serghd @  28.2.2012,  19:21 Найти цитируемый пост)
не считывая отдельно каждую из таблиц прав

Проинтуичить, что ли?  smile 

Автор: serghd 28.2.2012, 20:20
Цитата(Akina @ 28.2.2012,  19:59)

 Из описания ни хрена не удаётся понять.

ну как ещё описать, чтобы было понятно - хз. И так вроде по буквам разложил. 
Пусть будет пример: есть учитель, ученик и родитель. У всех свои разные права, хотя при этом все являются пользователями. 

Таблица users:
id | login

Таблица pupils:
id | user_id | class

Таблица teachers:
id | user_id | subject

Таблица parents:
id | user_id | pupil_id

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

Цитата(Akina @ 28.2.2012,  19:59)

 Кроме того, что ACL реализованы через одно место - право на объект есть одна сущность, и негоже размазывать её по куче таблиц

Как раз-таки считаю совсем наоборот - пихать в одну общую таблицу кучу ненужных для некоторых типов пользователей информацию считаю злом, поэтому и разделил. Или вы предлагаете дополнительное поле в таблицу users с "перечислением" доступных прав? Думал, но не то это, т.к. нужна дополнительная инфа, которая отмечена в таблицах примера выше по каждому типу пользователя.

Автор: Zloxa 28.2.2012, 20:39
Цитата(serghd @  28.2.2012,  20:20 Найти цитируемый пост)
После авторизации надо знать какие права у пользователя, т.к. например родитель может быть в том же время и учителем.

на счет левого соеднинеия, вы уже конечно в курсе
Код

select users.id
   ,case when pupils.user_id is null then 'N' else 'Y' end is_pupil 
   ,case when teachers .user_id is null then 'N' else 'Y' end is_teacher
   ,case when parents.user_id is null then 'N' else 'Y' end is_parent
from users
left join pupils on users.id = pupils.user_id
left join teachers on users.id = teachers.user_id
left join parents on users.id = parents.user_id
where loogn = :login


ну или через объединение, как предлагал Акина
Код

select 'is pupil' from pupils where user_id = :user_id
union all
select 'is teacher' from teachers where user_id = :user_id
union all
select 'is parent' from parents where user_id = :user_id


Но такой дизайн для ACL - да, весьма странен.  smile 

Автор: serghd 28.2.2012, 20:41
Цитата(Zloxa @ 28.2.2012,  20:39)
Но такой дизайн для ACL - да, весьма странен.  smile

можете порекомендовать другой?

Автор: Zloxa 28.2.2012, 20:46
Цитата(serghd @  28.2.2012,  20:41 Найти цитируемый пост)
можете порекомендовать другой? 


Попытаться вас в чем то побуеждать? Ни в коем разе, с чего вы подумали? Просто поделился наблюдением.

Автор: serghd 28.2.2012, 20:55
Цитата(Zloxa @ 28.2.2012,  20:46)
Цитата(serghd @  28.2.2012,  20:41 Найти цитируемый пост)
можете порекомендовать другой? 


Попытаться вас в чем то побуеждать? Ни в коем разе, с чего вы подумали? Просто поделился наблюдением.

да нет, я вполне серьёзно спросил. Если есть способ лучше  - почему бы не использовать.

Автор: serghd 28.2.2012, 21:47
придумал

"SELECT 
   (SELECT COUNT(id) FROM `administrators` WHERE user_id = '".$user_id."') as admin, 
   (SELECT COUNT(id) FROM `form_masters` WHERE user_id = '".$user_id."') as form_master,
   (SELECT COUNT(id) FROM `teachers` WHERE user_id = '".$user_id."') as teacher,
   (SELECT COUNT(id) FROM `head_teachers` WHERE user_id = '".$user_id."') as head_teacher,
   (SELECT COUNT(id) FROM `pupils` WHERE user_id = '".$user_id."') as pupil,
   (SELECT COUNT(id) FROM `parents` WHERE user_id = '".$user_id."') as parent"

Вывод:
Array ( [admin] => 1 [head_teacher] => 1 [form_master] => 0 [teacher] => 1 [pupil] => 1 [parent] => 0 ) 

всё ок, в базе так и лежит. Если равно 0, то данных прав нет.

Автор: Akina 28.2.2012, 22:06
Месье знает толк в извращениях... но коли оно нравится - так и пусть его.
А поскольку сие явно поделка ну максимум в размере районо, то база большой не будет, производительность пофиг... сойдёт.

Автор: serghd 28.2.2012, 22:23
Цитата(Akina @ 28.2.2012,  22:06)
Месье знает толк в извращениях... но коли оно нравится - так и пусть его.
А поскольку сие явно поделка ну максимум в размере районо, то база большой не будет, производительность пофиг... сойдёт.

а, ну то есть по поводу ACL вы уже не против? Ибо предложений ещё не увидел))

Автор: Akina 28.2.2012, 22:27
Цитата(serghd @  28.2.2012,  23:23 Найти цитируемый пост)
ну то есть по поводу ACL вы уже не против

Да мне по барабану... хотите делать через определённое место - делайте.
Или почитайте, как организовано хранение прав и вычисление эффективных прав в приличных файловых системах и в сервисах каталога.

Автор: serghd 28.2.2012, 22:36
Цитата(Akina @ 28.2.2012,  22:27)
Цитата(serghd @  28.2.2012,  23:23 Найти цитируемый пост)
ну то есть по поводу ACL вы уже не против

Да мне по барабану... хотите делать через определённое место - делайте.
Или почитайте, как организовано хранение прав и вычисление эффективных прав в приличных файловых системах и в сервисах каталога.

если бы дело касалось c++, то на права пользователя я бы выделил тип int, и комбинировал бы их побитовыми операциями (предварительно описавши енум для работы с ними). Это наименее затратный способ. В плане БД ничего удобнее я ещё не придумал.

Автор: Akina 29.2.2012, 07:45
Цитата(serghd @  28.2.2012,  23:36 Найти цитируемый пост)
В плане БД ничего удобнее я ещё не придумал.

Судя по тексту выше, у Вас MySQL. Ну так он распрекрасно умеет выполнять побитовые логические операции. 
Единственное ограничение - их результат всегда 64 бит беззнаковый, соответственно и права/маски рекомендуется хранить в том же типе.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)