Mysql Помогите правильно составить запрос select из select

simbatron

Новичок
Есть три таблицы:

Код:
select * from jobs;
+--------+----------+------------------+-------------+-------------+--------------+--------+------------+----------+
| num_dt | num_sort | status_dt        | exchange_dt | name_dt     | group_obj_id | obj_id | date_dt    | time_dt  |
+--------+----------+------------------+-------------+-------------+--------------+--------+------------+----------+
|      2 |        1 | работает         |           0 | delete_site |            2 |      4 | 2016-09-14 | 01:10:30 |
+--------+----------+------------------+-------------+-------------+--------------+--------+------------+----------+
Код:
select * from group_obj;
+--------+----------------+----------+
| num_dt | name_dt        | table_dt |
+--------+----------------+----------+
|      1 | Сервера        | servers  |
|      2 | Домены         | domains  |
|      3 | Темы           | thems    |
+--------+----------------+----------+
Код:
select * from domains;
+--------+------------+-----------+
| num_dt | name_dt    | server_id |
+--------+------------+-----------+
|      4 | ramfish.ru |        13 |
|      5 | site-1.ru  |        14 |
+--------+------------+-----------+
Мне нужно выбрать сайт ramfish.ru из таблицы domains в подзапросе.
Основной запрос идет в таблицу jobs, потом по полю из этой таблицы group_obj_id в подзапросе получаем поле table_dt (у которого значение domains) и это значение domains послужит значением таблицы для подзапроса который вернет уже поле name_dt (у которого значение ramfish.ru)

Вот я сделал запрос:
select SQL_CALC_FOUND_ROWS num_dt as num_line, (select name_dt from (select table_dt from group_obj where num_dt=t.group_obj_id limit 1) as t1 where num_dt=t.obj_id limit 1) as obj_dt from jobs as t order by num_dt LIMIT 0, 100
но он не работает, выдает Column not found: 1054 Unknown column 't.group_obj_id' in 'where clause''

Помогите пожалуйста правильно составить запрос.
 

simbatron

Новичок
Я не брал ), я надеялся что если так возможно то кто так умеет, тот подскажет как это сделать правильно.
 

Фанат

oncle terrible
Команда форума
Ну вот теперь ты знаешь, что легким движением руки превратить содержимое колонки в ее название почему-то невозможно.

Дальше ты можешь сделать логичный вывод о том, что динамически использовать в запросе можно только данные, и соответствующим образом перестроить структуру таблиц.
 

antson

Новичок
Партнер клуба
@simbatron,
если твои три таблицы сервера, домены, темы можно свести к единой структуре, то
можно реализовать через http://dev.mysql.com/doc/refman/5.7/en/create-view.html
select 1 as group_obj, num_dt as id, name_sr as name from servers union select 2 ,num_dt as id, name_dt from domains union select 2,num_dt as id, name_th from themes
обзовём такую въюшку например view_name

тогда запрос можно строить по объединению
select * from jobs j ,view_name v where j.group_obj_id = v.group_obj and j.obj_id=v.id
 

antson

Новичок
Партнер клуба
@Фанат, логичнее, но это если не очень много рефакторинга другого кода и разработка ведется одним человеком.
 

simbatron

Новичок
Вообще мне не хочется в одну таблицу собирать (я понимаю что так можно) и домены и сервера и тематики и ... что там еще будет добавляться, там везде разная информация хранится, и вообще все в одну таблицу валить из за того что запрос не получается сделать мне не хочется.
Пробую сделать хранимую функцию:
Код:
DELIMITER $$
CREATE
    FUNCTION `baza`.`object`(group_obj_id INT, obj_id INT) RETURNS VARCHAR(100)
    BEGIN
    DECLARE result VARCHAR(100);
    DECLARE obj_table VARCHAR(100);
    DECLARE query_string VARCHAR(300);
    SELECT table_dt INTO obj_table FROM group_obj WHERE num_dt=group_obj_id;
    SET @query_string := CONCAT('SELECT name_dt INTO result FROM ', obj_table, ' WHERE num_dt=obj_id');
    PREPARE dinamic_query FROM @query_string;
    EXECUTE dinamic_query;
    DEALLOCATE PREPARE dinamic_query;
    RETURN(result);
    END$$
DELIMITER ;
чтоб потом её просто использовать в запросе, но опять же динамические запросы не разрешает делать: "Dynamic SQL is not allowed in stored function or trigger"
 

Фанат

oncle terrible
Команда форума
Да-да. Не хочется строить дом из кирпича потому что в деревянном пол проваливается.
 

fixxxer

К.О.
Партнер клуба
Ну вообще в данном случае задача решается left join-нами на все три таблицы и case-ом.

Если хочется с неограниченным числом таблиц и на лету, можно в N запросов (где N = число таблиц + 1), см. реализацию polymorphic relations в Eloquent ORM. В случае, если поля совпадают, можно и в 2 запроса, но во втором будет адский union all N-1 раз.
 

Фанат

oncle terrible
Команда форума
Ну в общем здесь классическая проблема "EAV или другие извращения".
Так что да, возможно, что решение @antson не такое уж кривое и при небольшом размере таблиц вполне прокатит.
 

fixxxer

К.О.
Партнер клуба
Ну, да, как-то так. При небольшом размере таблиц и малой вероятности появления четвертой-пятой-шестой я бы, наверное, лефт-джойнами сделал.

Вьюх в mysql я боюсь с тех пор, когда напоролся на баг с игнорированием use/force index в оных, причем explain врал. Хотя его, вроде, исправили давно. Но осадочек остался.

Пробую сделать хранимую функцию:
В хранимке ты не сделаешь ничего такого, чего нельзя сделать php-кодом.
 

antson

Новичок
Партнер клуба
ой ну сколько там записей будет ;)
темплаты 5-10 тыс
домены менее 10 тыс
серверы до 10 штук
 

simbatron

Новичок
В хранимке ты не сделаешь ничего такого, чего нельзя сделать php-кодом.
Это понятно что можно запросов из php наделать сколько хочешь, но тогда как к этим данным применять order by, where, ...

если твои три таблицы сервера, домены, темы можно свести к единой структуре, то
можно реализовать через http://dev.mysql.com/doc/refman/5.7/en/create-view.html
select 1 as group_obj, num_dt as id, name_sr as name from servers union select 2 ,num_dt as id, name_dt from domains union select 2,num_dt as id, name_th from themes
обзовём такую въюшку например view_name

тогда запрос можно строить по объединению
select * from jobs j ,view_name v where j.group_obj_id = v.group_obj and j.obj_id=v.id
Изучаю эту тему, раньше не пользовался, только мне думается там будут ограничения похожие на "Dynamic SQL is not allowed in stored function or trigger"
Я же сделал процедуру с динамическим запросом, с процедурой все срабатывает, потом сделал функцию с вызовом этой процедуры и эта функция естественно не заработала из за "Dynamic SQL is not allowed in stored function or trigger"

Я даже начал смотреть в сторону postgresql но пока только интересуюсь, там вроде побольше пространства для маневра.
 

simbatron

Новичок
Еще такой вариант возможен: Компиляция и установка определяемых пользователем функций
Можно на С написать свою функцию которая делает запрос в mysql и применять её в запросе, но такую функцию нужно компилировать для каждой системы отдельно, это тоже серьезное ограничение, потом в другом месте применять такую функцию не удобно будет.
 

Фанат

oncle terrible
Команда форума
Делай вью уже и не кочевряжься.
С точки зрения производительности это конечно жесть, ну так у тебя и не хайлоад
 

fixxxer

К.О.
Партнер клуба
В postgresql с этим все ровно так же. Во всех РСУБД одинаково. Сначала парсится SQL-запрос в абстрактное дерево (где уже четко заданы имена таблиц и полей), потом по ним строится план выполнения запроса (опять же для конкретных таблиц, полей и условий), потом этот план выполняется.
 
Сверху