SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 22.01.2010 12:20:39

Questor
Участник
Зарегистрирован: 17.01.2010
Сообщений: 6

Full outer join?

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


mysql> select * from partition;
+-------------+---------------+-----------------+
| PartitionID | PartitionName | PartitionSwitch |
+-------------+---------------+-----------------+
|           1 | Улица         |               1 |
|           2 | Комната       |               0 |
+-------------+---------------+-----------------+
2 rows in set
 



mysql> select * from section;
+-----------+-------------+-------------+---------------+
| SectionID | SectionName | PartitionID | SectionSwitch |
+-----------+-------------+-------------+---------------+
|         1 | Суккулент   |           2 |             1 |
|         2 | Дерево      |           1 |             1 |
|         3 | Трава       |           1 |             0 |
+-----------+-------------+-------------+---------------+
3 rows in set
 



mysql> select * from item;
+--------+-----------------+-----------+------------+
| ItemID | ItemName        | SectionID | ItemSwitch |
+--------+-----------------+-----------+------------+
|      1 | Денежное дерево |         1 |          0 |
|      2 | Яблоня          |         2 |          1 |
|      3 | Газонная трава  |         3 |          1 |
|      4 | Груша           |         2 |          1 |
+--------+-----------------+-----------+------------+
4 rows in set
 


Таким образом мы выбираем только включенные элементы (растения):


mysql> select
    P.PartitionName,
    S.SectionName,
    I.ItemID,
    I.ItemName
from
    item as I
    left join section as S on S.SectionID=I.SectionID
    left join partition as P on P.PartitionID=S.PartitionID
where
    P.PartitionSwitch=1
    and
    S.SectionSwitch=1
    and
    I.ItemSwitch=1
group by
    I.ItemID
;
+---------------+-------------+--------+----------+
| PartitionName | SectionName | ItemID | ItemName |
+---------------+-------------+--------+----------+
| Улица         | Дерево      |      2 | Яблоня   |
| Улица         | Дерево      |      4 | Груша    |
+---------------+-------------+--------+----------+
2 rows in set
 


Основная задача: одним запросом выбрать элементы (растения) таким образом, чтобы получился результат (для каждого включенного элемента соответствовал каждый выключенный):


+---------------+-------------+--------+----------+--------+-----------------+
| PartitionName | SectionName | ItemID | ItemName | ItemID | ItemName        |
+---------------+-------------+--------+----------+--------+-----------------+
| Улица         | Дерево      |      2 | Яблоня   |      1 | Денежное дерево |
| Улица         | Дерево      |      2 | Яблоня   |      3 | Газонная трава  |
| Улица         | Дерево      |      4 | Груша    |      1 | Денежное дерево |
| Улица         | Дерево      |      4 | Груша    |      3 | Газонная трава  |
+---------------+-------------+--------+----------+--------+-----------------+
 


Не спрашивайте для чего это нужно -- это составная часть более глобальной задачи. ;-) Огромное спасибо.

Неактивен

 

#2 22.01.2010 13:24:55

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Full outer join?

Ну так и объедините еще раз с таблицей item, в которой растения выключены?

Кстати, а как вы включаете траву? Я бы включил в такую погоду wink

Неактивен

 

#3 22.01.2010 13:40:24

Questor
Участник
Зарегистрирован: 17.01.2010
Сообщений: 6

Re: Full outer join?

Честно говоря, если бы это была реальность, я бы включал одно денежное дерево. И тогда трава зимой -- не вопрос wink

Возможно, вы не поняли немного суть вопроса. Дело в том, что выключенные растения -- это не просто (ценный мех):


mysql> select * from item where ItemSwitch=0;
+--------+-----------------+-----------+------------+
| ItemID | ItemName        | SectionID | ItemSwitch |
+--------+-----------------+-----------+------------+
|      1 | Денежное дерево |         1 |          0 |
+--------+-----------------+-----------+------------+
1 row in set
 


Это немного сложнее:


mysql> select
    I.*
from
    item as I
left join section as S on S.SectionID=I.SectionID
left join partition as P on P.PartitionID=S.PartitionID
where
    P.PartitionSwitch=0
    or
    S.SectionSwitch=0
    or
    I.ItemSwitch=0
group by
    I.ItemID
;

+--------+-----------------+-----------+------------+
| ItemID | ItemName        | SectionID | ItemSwitch |
+--------+-----------------+-----------+------------+
|      1 | Денежное дерево |         1 |          0 |
|      3 | Газонная трава  |         3 |          1 |
+--------+-----------------+-----------+------------+
2 rows in set
 


Улавливаете разницу? Так вот, как объединить вот эти 2 запроса (для включенных и выключенных растений) в один как можно изящнее?

Неактивен

 

#4 22.01.2010 13:53:51

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Full outer join?

SELECT …
FROM (первый запрос) t1
JOIN (второй запрос) t2 USING (SectionID)

Но организация данных правда очень странная и непонятная smile

Кстати, когда начнет тормозить, все равно прийдется добавлять в
items доп.поле InheritedSwitch, и тогда запросы станут простыми.

Неактивен

 

#5 22.01.2010 14:07:26

Questor
Участник
Зарегистрирован: 17.01.2010
Сообщений: 6

Re: Full outer join?

paulus написал:

Но организация данных правда очень странная и непонятная smile

А как бы Вы организовали (надеюсь, иерархия ясна)?

paulus написал:

SELECT …
FROM (первый запрос) t1
JOIN (второй запрос) t2 USING (SectionID)

Я тоже так эксперементировал, но слишком громоздко выходит. Тем более структура БД приведена в упрощенном виде. В реальности будет еще хужее sad Нутром чувствую, что должно какое-то более простое решение существовать.

paulus написал:

Кстати, когда начнет тормозить, все равно прийдется добавлять в
items доп.поле InheritedSwitch, и тогда запросы станут простыми.

А если предков-таблиц (детей) будет несколько? А если несколько параллельных? К примеру, у разделов (Section) в качестве таблицы-предка может выступать таблица пользователей, которые создают эти самые разделы. И пользователей тоже нужно отключать. Допустим, через триггеры это весьма сложно будет реализовать, тем более та же самая проверка, только не вверх по дереву, а вниз.

Неактивен

 

#6 22.01.2010 14:55:38

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Full outer join?

Неясен смысл запроса, поэтому не понятна и организация данных smile

Если несколько параллельных состояний включенности, то и запрос прийдется
переписывать smile

UPD: Кстати, попробуйте выбирать тупо все записи и произведение состояний
включенности. Возможно, вывод этой выборки сподвигнет Вас на создание
простой группировки smile

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson