Объединение 3 таблиц Mysql. Вывод массива результата объединения, при опред. условии.

Гриша К.

Новичок
Объединение 3 таблиц Mysql. Вывод массива результата объединения, при опред. условии.

Здравствуйте.
# У меня есть задача, которую я не могу выполнить, я описываю ее ниже "## ЧТО Я ХОЧУ СДЕЛАТЬ ##".
# У меня есть одна идея "# МОИ СООБРАЖЕНИЯ #", но для этого мне нужно объединить 3 таблицы левосторонним объединением, чего я немогу сделать. И в общем-то если я смогу это сделать, возможно задача будет решена.
# И возможно посмотрев приведенные таблицы и прочитав интересующие меня условия вывода данных, вы сможете предложить простое решение, так как у меня знаний немного в PHP, и возможно я просто невижу простого решения.

PHP:
ORDERS
|---------|-------------|--------|-----|----------|
| orderid | customerdid | amount | pay |   date   |
|---------|-------------|--------|-----|----------|
|    1    |      1      |   25   | yes | 01-01-07 |
|    2    |      2      |   25   | no  | 01-01-07 |
|    3    |      3      |   25   | no  | 01-01-07 |
|    4    |      4      |   25   | yes | 01-01-07 |
|---------|-------------|--------|-----|----------|

ORDER_DETAILS
|---------|-------------|------------|--------|----------|-----------|
| orderid |  productid  |     iso    | Cityid |   foto   | signature |
|---------|-------------|------------|--------|----------|-----------|
|    1    |      1      |     RUS    |  11    |  1.jpg   |   none    |
|    2    |      2      |     RUS    |  11    |  2.jpg   |   none    |
|    3    |      3      |     RUS    |  12    |  3.jpg   |   none    |
|    4    |      4      |     AUT    |  14    |  4.jpg   |   none    |
|---------|-------------|------------|--------|----------|-----------|

COUNTRIES
|------------|--------------|
|     iso    |   country    |
|------------|--------------|
|     AUS    |  Австралия   |
|     AUT    |   Австрия    |
|     AZE    |  Азербайджан |
|     RUS    |    Россия    |
|------------|--------------|
PHP:
// ФУНКЦИЯ ВЫВОДИТ МАССИВ Из ПОЛЯ "iso", и ПОЛЯ "country"
function get_country()
{
   //... 	
   $query = 'select iso, country
             from countries'; 
   $result = @mysql_query($query);
   //...  
   $result = db_result_to_array($result);
   return $result; 
}

// ФУНКЦИЯ ПРИНИМАЕТ МАССИВ функции get_country() и выводит весь список стран в виде ссылок
function display_country($country_array)
{
  //...
  foreach ($country_array as $row)
  { 
    echo "<a href=\"$row[iso]\">$row[country]</a>\n"; 
  }  

}

//
$country_array = get_country();

display_country($country_array);

######## ЧТО Я ХОЧУ СДЕЛАТЬ ##########

Я хочу сделать так, чтобы если столбец "pay" неравняется 'yes', то тогда выводим Страны например виде текста
PHP:
function display_country($country_array)
{
  //...
  foreach ($country_array as $row)
  { 
    if ($row[pay]=='yes')
     echo "<a href=\"$row[iso]\">$row[country]</a>\n";
    else
     echo "$row[country]\n";
  }  

}
Если просто объединить все 3 таблицы, то соответсвенно буду выводиться только те города, где "ordrid" не равняется null


########## МОИ СООБРАЖЕНИЯ ###########

У меня есть такая идея:
1) В функции get_country() извлеч данные таким образом где "pay" = YES
$query = "select DISTINCT C.iso, C.country, O.pay
from countries as C, order_details as OD, orders as O
where C.iso = OD.iso and OD.orderid = :confused:rderid and O.pay = 'Yes'";

2) Сделать функцию get_country_1(), где используя левостороннее объядинение извлеч все остальные данные из тех же столбцов, но там где "pay" = NO и "orderid" имеет пустое значение (is null)
Но я не знаю как объединить 3 таблицы левосторонним объединением, у меня получается объединить только 2 таблицы:
$query = "select DISTINCT countries.iso, countries.country
from countries left join order_details using (iso) where order_details.orderid is null";

3) Объединить массивы этих функций и вывести полученный массив;

//
$country_array = get_country();
$country_array_1 = get_country_1();

$country_array_merge = array_merge($country_array, $country_array1);

display_country($country_array); // В таком случае массив будет содержать значение столбца "pay" и я могу к нему обратиться
PHP:
 

Vander

Новичок
А по какому принципу связанны ORDERS и ORDER_DETAILS
получается что у каждой страны pay может быть равен yes одновременно с no
Ну с [telepate mode]
[SQL]
select a.iso, b.country, c.pay
from `ORDER_DETAILS` a
left join
`COUNTRIES` b
on (a.iso like b.iso)
left join
ORDERS c
on (a.`orderid`=c.`orderid`)
[/SQL]
 

zarus

Хитрожопый макак
Структура таблиц кривая, измени структуру, и сможешь делать через 1 join.
PHP:
ORDERS:
// Я так понимаю, что 1 заказ может быть сделан из 1 города 1 страны,
// поэтому нет смысла вносить эту информацию в таблицу со списком заказанных товаров
orderid | customerdid | pay | date | iso | Cityid | signature
// в список приобретенных товаров вообще нужно занести только 3 поля - номер заказа, номера заказанных товаров и их количество
// что это поле делает в таблице заказов вообще не понятно
ORDER_DETAILS:
orderid | productid | amount 
// Без изменений - справочник стран
COUNTRIES
iso | country
// Справочник товаров, в них уже будет содержаться подробная информация о товарах
PRODUCTS
productid  | foto ...
-~{}~ 15.02.06 17:28:

з.ы. И что за бред pay = yes|no? Чем не нравится булев тип? На худой конец можно было бы использовать 0 (pay) | 1 (no), и задачу можно было бы решить через сложение.
 

Гриша К.

Новичок
Vander и zarus спасибо за ответы.


Связь между ORDERS и ORDER_DETAILS

При осуществлении заказа в таблицу ORDERS записывается номер заказа (orderid),
в следующей колонке записывается идентификатор клиента (customerid) соотвествуйщий ид. в таблицы customers (данные о пользователе), дальше записывается цена (amount), потом по умолчанию записывается информация об оплате (pay) = 'No' (после оплаты администратор устанавливает 'Yes') и дальше записывается дата.

В таблицу ORDER_DETAILS записывается номер заказа (orderid) и идентификатор товара (productid), эти столбцы есть primary_key,
дальше записывается код страны (iso) соответсвующий коду страны таблицы COUNTRIES,
потом записывается идентификатор города (cityid), дальше записывается "объект", который загружает пользователь,
и записывается подпись (signature) для объекта.


Для одного города (citiyid) одной страны (countryid), может быть всего четыри заказа (orderid), т.е. productid = 1, 2, 3, 4. Пользователь не может в одном городе сделать больше 1 заказа.
Например для города Москвы, может быть лиш один заказ с productid = 4, (и яне забываю про то, что город Москва есть и в Америке, и также с некоторыми другими городами)
PHP:
|---------|-------------|------------|--------|----------|-----------| 
| orderid |  productid  |     iso    | Cityid |   foto   | signature | 
|---------|-------------|------------|--------|----------|-----------| 
|    5    |      1      |     RUS    |  11    |  5.jpg   |   none    | 
|    6    |      2      |     RUS    |  11    |  6.jpg   |   none    | 
|    7    |      3      |     RUS    |  11    |  7.jpg   |   none    | 
|    8    |      4      |     RUS    |  11    |  8.jpg   |   none    | 
|---------|-------------|------------|--------|----------|-----------|
На одной из страниц сайта мен нужно выводить список всех стран (231), но ту страну, в которой есть хотябы один город в котором помещен хотя бы 1 "объект" из 4 возможных, нужно пометить. Например:
Австралия
Австрия
Азербайджан
Россия

Надеюсь я смог вам полностью донести систуме работы, и поэтому zarus
например такое координальное изменение таблиц не подходит.
Если можете, поясните пожалуйста:
Чем не нравится булев тип? На худой конец можно было бы использовать 0 (pay) | 1 (no), и задачу можно было бы решить через сложение.
Возможно стоит перенести колонку "pay" из ORDERS в ORDER_DETAILS. попробую обдумать такой вариаант.

-~{}~ 15.02.06 22:02:

Нащлось решение.
При моих условиях можно просто объединить таблицы ORDERS и ORDER_DETAILS по полю orderid, и назвать эту таблицу ORDERS.

А дальше простой sql запрос
$query = "select DISTINCT countries.countryiso, countries.countryrus, orders.pay
from countries left join orders
on countries.countryiso = orders.countryiso";

И затем вывожу так:
foreach ($country_array as $row)
{
if ($row[pay]=='yes')
echo "<a href=\"$row[iso]\">$row[country]</a>\n";
else
echo "$row[country]\n";
}

Ну такое объединение получилось, потому что у меня это позволяют условия, а если бы нет, то пришлось бы работать с 3 таблицами.

===================================
Осталось два небольших вопроса:
(1) Скажите пожалуйста, можно ли объединить 3 таблицы используя левостороннее объединение (left join).
(2)Разъясните пожалуйста эту цитату
Чем не нравится булев тип? На худой конец можно было бы использовать 0 (pay) | 1 (no), и задачу можно было бы решить через сложение.
 

zarus

Хитрожопый макак
>> Чем не нравится булев тип?
Булев тип - это true | false. Зачем использовать текстовое поле длиной в N байт там, где можно использовать поле в 1 бит?

>> На худой конец можно было бы использовать 0 (pay) | 1 (no), и задачу можно было бы решить через сложение.
Обусловлено моим пониманием твоих условий задачи - вывести список всех стран, где есть НЕоплаченные заказы. Но твое второе объяснение изменило суть задачи.

>> Ну такое объединение получилось, потому что у меня это позволяют условия, а если бы нет, то пришлось бы работать с 3 таблицами.
А лучше прочитать литературу по проектированию и нормализации структуры баз данных. Очень полезная вещичка, чтобы потом не пришлось ломать голову над 4-5-6 joinами.
 

Гриша К.

Новичок
zarus, литературу я купил. Mysql справочник по языку, а так пользуюсь разработкой веб приложений с помощью PHP и MYSQL (Второе издание).
По поводу true и false я не понял что записывать в базу данных, начал искать в книге булкв тип, ненашел я. Только если указать тип столбца not null или null, если вы это имели ввид. Но не понимаю тогда, как к этому обращать.
Если можете, то разъясните пожалуйста.
 

zarus

Хитрожопый макак
Автор оригинала: Гриша К.
zarus, литературу я купил. Mysql справочник по языку, а так пользуюсь разработкой веб приложений с помощью PHP и MYSQL (Второе издание).
По поводу true и false я не понял что записывать в базу данных, начал искать в книге булкв тип, ненашел я. Только если указать тип столбца not null или null, если вы это имели ввид. Но не понимаю тогда, как к этому обращать.
Если можете, то разъясните пожалуйста.
Да, действительно, не нашел в MySQL булева типа, но там ведь есть TINYINT. Использовать 0 - оплачено, и 1 - неоплачено. ДА и индексы будут занимать меньше места.
Собственно, это уже к Вашей проблеме не относится. Займитесь лучше перепроектированием таблиц базы данных. Сейчас Ваши таблицы спроектированы ужасно.
 

Гриша К.

Новичок
zarus, спасибо большое за разъяснение, теперь я вас понял.
Ну а таблицы у меня сейчас сделаны таким образом, что я легко добираюсь до нужных эелементов.
Я все таки здесь полностью не раскрыл суть всего этого, еслби бы вы знали, то я думаю, что вы подругому бы увидели всю суть такой структуры.
И то что таблицы ORDERS и ORDER_ITEMS должны быть объеденены, это полюбому.
Я теперь все извлекаю в легкую так как мне надо.
Ну все и спасибо что давали мне объяснения.
 

zarus

Хитрожопый макак
>> И то что таблицы ORDERS и ORDER_ITEMS должны быть объеденены, это полюбому.
Утверждение лишь убеждает меня, что таблицы спроектированы неверно. Не зависимо от сути. Но воля Ваша, Вам же с ними и мучаться.
 

Гриша К.

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