Таблицы соединения MySQL, где имя таблицы является полем другой таблицы

У меня 5 столов. Один основной и 4 дополнительных (у них разные колонки).

  1. объекты
  2. obj_mobiles
  3. obj_tablets
  4. obj_computers

Вот структура моей основной таблицы (объектов).

ID | тип | имя | так далее...

Итак, что я хочу сделать, это объединить объекты с другими (obj_mobiles, obj_tablets,...) таблицами, в зависимости от поля типа. Я знаю, что должен использовать динамический SQL. Но я не могу сделать процедуру. Я думаю, что это должно выглядеть примерно так.

SELECT objects.type into @tbl FROM objects;
PREPARE stmnt FROM "SELECT * FROM objects AS object LEFT JOIN @tbl AS info ON object.id = info.obj_id"; 
EXECUTE stmnt;
DEALLOCATE PREPARE stmnt;

Также псевдокод

SELECT * FROM objects LEFT JOIN [objects.type] ON ... 

Кто-нибудь может выложить процедуру? Также я хочу иметь все строки, а не только 1 строку. Спасибо.


person Cyberon    schedule 13.01.2012    source источник


Ответы (3)


Если вам нужны все строки (массовый вывод), а не одна строка за раз, приведенное ниже должно быть быстрым, а также вывод для всех строк будет содержать все столбцы.

Рассмотрим ниже поля таблиц. obj_mobiles - ID | М1 | M2 obj_tablets - ID | Т1 | T2 obj_computers - ID | С1 | Объекты C2 - ID | тип | имя | так далее.,

Select objects.*, typestable.*
from (
    select ID as oID, "mobile" as otype, M1, M2, NULL T1, NULL T2, NULL C1, NULL C2 from obj_mobiles 
    union all
    select ID as oID, "tablet" as otype, NULL, NULL, T1, T2, NULL, NULL from obj_tablets 
    union all
    select ID as oID, "computer" as otype, NULL, NULL, NULL, NULL, C1, C2 from obj_computers) as typestable 
        left join objects on typestable.oID = objects.ID and typestable.otype = objects.type;

+------+--------------------+----------+------+----------+------+------+------+------+------+------+
| ID   | name               | type     | ID   | type     | M1   | M2   | T1   | T2   | C1   | C2   |
+------+--------------------+----------+------+----------+------+------+------+------+------+------+
|    1 | Samsung Galaxy s2  | mobile   |    1 | mobile   |    1 | Thin | NULL | NULL | NULL | NULL |
|    2 | Samsung Galaxy Tab | tablet   |    2 | tablet   | NULL | NULL | 0.98 |   10 | NULL | NULL |
|    3 | Dell Inspiron      | computer |    3 | computer | NULL | NULL | NULL | NULL | 4.98 | 1000 |
+------+--------------------+----------+------+----------+------+------+------+------+------+------+

Таблица создается, как показано ниже.

mysql> create table objects (ID int, name varchar(50), type varchar (15));
Query OK, 0 rows affected (0.05 sec)
mysql> insert into objects values (1, "Samsung Galaxy s2", "mobile"), (2, "Samsung Galaxy Tab", "tablet"), (3, "Dell Inspiron", "computer");
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0


mysql> create table obj_mobiles (ID int, M1 int, M2 varchar(10));
Query OK, 0 rows affected (0.03 sec)
mysql> insert into obj_mobiles values (1, 0.98, "Thin");
Query OK, 1 row affected (0.00 sec)


mysql> create table obj_tablets (ID int, T1 float, T2 int(10));
Query OK, 0 rows affected (0.03 sec)
mysql> insert into obj_tablets values (2, 0.98, 10);
Query OK, 1 row affected (0.00 sec)


mysql> create table obj_computers (ID int, C1 float, C2 int(10));
Query OK, 0 rows affected (0.03 sec)
insert into obj_computers values (3, 4.98, 1000);

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

create table temp_result as
Select objects.*, typestable.*
from (
    select ID as oID, "mobile" as otype, M1, M2, NULL T1, NULL T2, NULL C1, NULL C2 from obj_mobiles 
    union all
    select ID as oID, "tablet" as otype, NULL, NULL, T1, T2, NULL, NULL from obj_tablets 
    union all
    select ID as oID, "computer" as otype, NULL, NULL, NULL, NULL, C1, C2 from obj_computers) as typestable 
        left join objects on typestable.oID = objects.ID and typestable.otype = objects.type;

mysql> desc temp_result;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| ID    | int(11)     | YES  |     | NULL    |       |
| name  | varchar(50) | YES  |     | NULL    |       |
| type  | varchar(15) | YES  |     | NULL    |       |
| oID   | int(11)     | YES  |     | NULL    |       |
| otype | varchar(8)  | NO   |     |         |       |
| M1    | int(11)     | YES  |     | NULL    |       |
| M2    | varchar(10) | YES  |     | NULL    |       |
| T1    | float       | YES  |     | NULL    |       |
| T2    | int(11)     | YES  |     | NULL    |       |
| C1    | float       | YES  |     | NULL    |       |
| C2    | int(11)     | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
11 rows in set (0.00 sec)
person Harun Prasad    schedule 19.01.2012
comment
Это будет быстрее, чем решение Devart - person Harun Prasad; 19.01.2012
comment
Спасибо. Это то, что я ищу. - person Cyberon; 19.01.2012

Если objects является родительской таблицей, это означает, что objects.ID является уникальным объектом. Верно? Все остальные элементы (мобильные телефоны, планшеты, компьютеры) являются дочерними для объекта, а мобильный телефон и планшет не могут иметь одинаковый идентификатор. Если это так, то достаточно использовать этот простой запрос —

SELECT * FROM objects o
  LEFT JOIN obj_mobiles m
    ON o.id = m.ID
  LEFT JOIN obj_tablets t
    ON o.id = t.ID
  LEFT JOIN obj_computers c
    ON o.id = c.ID

Добавьте предложение WHERE для фильтрации типов, например: WHERE o.type = 'mobile'.

person Devart    schedule 17.01.2012
comment
Проверьте мое решение для повышения производительности запроса с меньшим количеством соединений. - person Harun Prasad; 19.01.2012

ИСПОЛЬЗУЙТЕ CONCAT, чтобы создать оператор подготовки. например.

@sql = CONCAT('SELECT * FROM objects AS object LEFT JOIN ', @tbl, ' AS info ON object.id = info.obj_id');
PREPARE stmnt FROM @sql;
...
person dar7yl    schedule 16.01.2012