Сап /б/, срочно нужна помощь с sql запросом. Имеется бд из трех табличек - пик 1 Формулировка задачи - пик 2 Мое решение - пик 3, но оно нихуя не работает, знаю одно что запрос должен быть написан с двумя not exist'aми В таблице work_area_dict: num - номер цеха area_num - номер участка В таблице persons: work_num - номер цеха area_num - номер участка Буду рад любой помощи
select * from profession pr join persons ps on ps.prof_code = pr.code join work_area wa on wa.area_num = ps.area_num where ps.category>4 and wa.num = 7
>>236437936 вот этого поддвачну, нахуй тут вообще было какие-то подзапросы хуевертить? В самом условии прям SQL имеется, выбрать всех гречневых из 7 участка с разрядом > 4
>>236436962 (OP) ``` SELECT prof_code FROM ( SELECT prof_code, area_num FROM persons GROUP BY prof_code, area_num HAVING COUNT(CASE WHEN category <= 4 THEN 1 END) = 0 ) AS good_professions INNER JOIN work_area_dict ON work_area_dict.area_num = good_professions.area_num WHERE work_area_dict.num = 7 ```
SELECT prof_code FROM ( SELECT prof_code, area_num FROM persons GROUP BY prof_code, area_num HAVING COUNT(CASE WHEN category <= 4 THEN 1 END) = 0 ) AS good_professions INNER JOIN work_area_dict ON work_area_dict.area_num = good_professions.area_num WHERE work_area_dict.num = 7 ;
А, там >4, не вижу уже нихрена, тогда вот там аноны ниже правильно пишут, что сначала вообще всех отобрать на >4 через having count, потом оставить только 7 цех, всё
>>236442250 Тебе написали выше, чтобы ты c not exist поменял на exist. Да и нахуя тебе прям через ебучие экзисты надо? Тебе выше всё готовое выложили, без выебонов. И вообще чтобы понимать сходу как это работает, надо года 3 отхуячить запросником.
Эксисты заебись использовать, например, когда тебе надо из одной выборки убрать/оставить что-то из другой выборки. Всё. Для всего остального есть другие команды.
мимо sql=кодер, пошёл смотреть документалку про Вьентам и баиньки
>>236442989 да бля, это хуйню по методичке нужно делать, и препод сказал тип через not exist надо решать, и я честно не понял нихуя как мой запрос исправить, чтоб он работал. Если просто not exist на exist менять, нихуя не работает
>>236443320 Вот и я не ебу, скажи преподу Оп, что он лох. Как минимум потому, что задача с условием типа >4 в sql в подавляющем большинтсве случаев решается через агрегацию и having
>>236443320 я написал выше, чем она мне не нравится. Тем, что она обязана перебрать все записи. Exists сходит в индекс и узнает, есть ли ХОТЬ ОДИН. А с агрегацией ты можешь собрать из 10000 гречневых выборку ради того, чтобы узнать, что среди них двачер 3 разряда на вал мотается.
>>236442877 >и да, твой count переберет всю таблицу, а not exists скорее всего чекнет индекс и будет иметь сложность lg или даже (1)
Какой нахер индекс? Индекс по подзапросу? Не удивлюсь, если он будет вызывать этот подзапрос на каждую строку ебучей таблицы и устроит тебе квадратичную сложность.
>>236443501 >я написал выше, чем она мне не нравится. Тем, что она обязана перебрать все записи. Exists сходит в индекс и узнает, есть ли ХОТЬ ОДИН. А с агрегацией ты можешь собрать из 10000 гречневых выборку ради того, чтобы узнать, что среди них двачер 3 разряда на вал мотается.
Ну, перебрать все записи людей из 7го цеха ей имхо и так и так придётся.
С аггрегацией будет так:
Отфильтровать work_num = 7 Отсортировать по prof_num, area_num Пройти и для каждого prof_num, area_num саггрегировать COUNT(category <= 4). Выкинуть, если COUNT > 0 Пропустить дубликаты prof_num
>>236444081 ну я не спорю, что тут пизданутая конструкция, но нелюбовь к поздапросам она откуда-то у людей берется, я не ебу откуда, хотя они часто значительно быстрее, чем неявное создание промежуточных таблиц внутри подзапроса с агрегатами, и тем более при бесконтрольном джойне такой выборки на другие таблицы.
>>236444516 Классический подзапрос может помочь запросу отработать быстрее просто за счет того, что в одну тычку уберёт часть верхнего множества. Ну если доводить до абсурда - можно поискать в одной таблице наличие записи в поле с индексом (через exists), а можно сделать count(*) по этому полю с условием where
типа select 1 where exists(select 1 from ttt where id = 99123)
Ох уж эти ебанутые запросы из нескольких таблиц с условиями. Последние несколько лет только и делаю, что пишу вместо них кучу простых запросов и расставляю нормально индексы. Увеличение скорости работы в тысячи раз.
>>236444882 >типа select 1 where exists(select 1 from ttt where id = 99123) >против select 1 from ttt where id = 99123 group by id having count() > 0
Так один хер же будет, не?
Сначала отфильтруется по id = 99123. Потом для этой одной строки "посчитается" count() и т.д.
ИМХО, подзапросы намного мощнее и с ними проще накосячить, тогда как аггрегатные выражения намного проще и ограниченней. Ты там можешь использовать только поля текущей строки.
>>236445283 А вообще, такие штуки забавно гонять на терабайтах данных, данные зашардованны по машинам и ты реально видишь все эти джойны на более низком уровне.
Видно сортироваки, поточные операции, оптимизации, вроде переноса условий наверх, и т.д.
Когда в MS работал, этим постоянно приходилось заниматься (снаружи это называют U-SQL).
>>236444081 вы же понимаете что ускоряете запрос по базе на 100 строк? тут хоть коррелированными подзапросами считать, хоть фуллсканы, всем по барабану, вы главное строки нужные верните.
>>236446498 Моя идея это искать наличие цеха (exists) и внутри каждого цеха наличие рабочих (exists) и отсутствие тех у кого меньше 4 разряда (not exists) ``` select from profession_dict where exists ( select from work_area_dict where num = 7 and exists ( select from persons where work_area_dict.area_num = area_num and profession_dict.code = prof_code ) and not exists ( select from persons where category < 4 and work_area_dict.area_num = area_num and profession_dict.code = prof_code ) ) ```
Ещё скорее всего должно быть category <= 4 (так как в условии строго > 4), но я скопировал с ОП поста.