Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737 Форумы портала PHP.SU :: Вопрос по объединению таблиц
$result=$db->query("SELECT DISTINCT parentmenu.name, submenu.sub_name FROM parentmenu INNER JOIN submenu ON `submenu`.parentid = `parentmenu`.id") or die($db->error);
while($row=$result->fetch_assoc())
{
echo$row['name']."<br />";
echo$row['sub_name'];
}
Тоесть я говорю в запросе, выбери мне родительское меню, дочернее меню(подменю) из таблицы, которое содержит родительское меню объединяя его с подменю на основе того, что родительский id у подменю, развен id у основного меню. Как то так.
Проблема в том, что родительское меню при выводе ДУБЛИРУЕТСЯ. Я же написал DISTINCT - а он должен прекращать дублирование. Скажите пожалуйста, почему так?
Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007 Откуда: Berlin
Помог: 707 раз(а)
teddy
Потому что JOIN присоединяет все строки. Он не может понять, что существует некая "вложенность" (вернее, можно сконструировать замысловатый запрос, но в Вашем случае этого не нужно) элементов.
Вам достаточно сделать JOIN, после чего правильно выводить данные в PHP
- Вы получите отсортированный массив. Всё, что нужно - это выводить заголовки (например, можно просто смотреть, не сменился ли родительский элемент, и, если да - выводить его; цикл остаётся одиночным. Можно вместо этого пройтись по массиву строк и собрать данные в двумерный массив - на Ваш вкус).
Если интересует "замысловатый" запрос, то - пример: http://forum.php.su/topic.php?fo...30376#1190130376
----- Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
teddy
Отправлено: 29 Июля, 2013 - 17:03:50
Участник
Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013
Помог: 91 раз(а)
EuGen пишет:
Вам достаточно сделать JOIN, после чего правильно выводить данные в PHP
Запрос который вы написали отличается от моего только ORDER BY - его я тоже добавил но результат не изменился...
Можно подробнее про "правильный" вывод в PHP? Я сначала вывожу родительское меню а потом дочернее вроде бы все правильно... Или может вы имели ввиду что в php есть специальная функция для работы с массивами которая удаляет дубли? Если да, то подскажите пожалуйста, какая это функция
А не, про функцию я ляпнул...ведь mysqli возвращает объект
Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007 Откуда: Berlin
Помог: 707 раз(а)
teddy пишет:
Запрос который вы написали отличается от моего только ORDER BY - его я тоже добавил но результат не изменился...
EuGen пишет:
Потому что JOIN присоединяет все строки. Он не может понять, что существует некая "вложенность" (вернее, можно сконструировать замысловатый запрос, но в Вашем случае этого не нужно) элементов.
$result=$db->query("SELECT DISTINCT parentmenu.name, submenu.sub_name FROM parentmenu INNER JOIN submenu ON `submenu`.parentid = `parentmenu`.id") or die($db->error);
$rgResult=[];
while($row=$result->fetch_assoc())
{
$rgResult[$row['name']][]=$row['sub_name'];
}
//var_dump($rgResult)
- как работать с rgResult, уверен, догадаетесь. Альтернативный вариант (за один проход, с проверкой, не сменился ли родитель) - оставляю Вам (но даю подсказку - в том варианте без ORDER BY уже нельзя).
----- Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
teddy
Отправлено: 29 Июля, 2013 - 18:17:59
Участник
Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013
Помог: 91 раз(а)
EuGen
Спасибо за внимание, Евгений )
Я посмотрю обязательно что да как... сходу пока не понимаю.. всегда были проблемы с JOIN-ами (Добавление)
Не доходит в упор.
Пробовал даже по другому. Получал из объекта массив потом при помощи array_unique пытался удалить дубли тоже не выходит...
Не доходит почему не срабатывает DISTINCT что он есть что его нет одно и тоже..
В мозгах ошибка уровня notice ))
Panoptik
Отправлено: 29 Июля, 2013 - 19:57:48
Постоянный участник
Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011 Откуда: Одесса, Украина
Помог: 131 раз(а)
DISTINCT работает только по одному полю, если вы в выражении SELECT указываете 2 и более полей для выборки, то все они должны быть соответственно равны другим значениям чтобы опустить повторяющие значения
к примеру наборы чисел
1 2 3
1 3 2
1 1 1
1 2 3
через дистинкт дадут
1 2 3
1 3 2
1 1 1
то есть абсолютно одинаковые результаты отсеются (Добавление)
если нужно убрать дублирующие значения по определенным полям при этом выбрать дополнительные, то пользуйте GROUP BY
----- Just do it
teddy
Отправлено: 29 Июля, 2013 - 20:11:12
Участник
Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013
Помог: 91 раз(а)
Panoptik пишет:
если нужно убрать дублирующие значения по определенным полям при этом выбрать дополнительные, то пользуйте GROUP BY
Не совсем то. Я уже пробовал, но тогда подкатегории выводятся только 1 раз, а остальные не выводятся
EuGen
Отправлено: 30 Июля, 2013 - 13:12:17
Профессионал
Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007 Откуда: Berlin
Помог: 707 раз(а)
teddy
Всё же, я так и не понял, что же именно не получается.
mysql>SELECT tbl20130730_parent.title AS category, tbl20130730_child.title AS item FROM tbl20130730_parent LEFTJOIN tbl20130730_child ON tbl20130730_child.parent_id=tbl20130730_parent.id;
$rConnect=new mysqli('localhost','user','password','test') or exit(mysqli_error());
$rSelect=$rConnect->query('SELECT tbl20130730_parent.title AS category, tbl20130730_child.title AS item FROM tbl20130730_parent LEFT JOIN tbl20130730_child ON tbl20130730_child.parent_id=tbl20130730_parent.id') or exit(mysqli_error());
- примерный результат.
Всё-таки вариант без сбора данных в промежуточный массив оставлю Вам.
----- Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
teddy
Отправлено: 30 Июля, 2013 - 14:17:48
Участник
Покинул форум
Сообщений всего: 1462
Дата рег-ции: Апр. 2013
Помог: 91 раз(а)
EuGen
Упс, столько написали ) Даже стыдно как то стало, что поднял эту тему )) Спасибо за ваши старания и внимание!
Вот в этом и заключается ступор ) Я хотел решить вопрос одним циклом, цикл в цикле - так уже я решал честно говоря без промежуточного массива
Если честно мне это меню особо не нужно, у меня есть рабочее "решение", я просто взялся за этот скрипт для тренировки JOIN-ов... Получается так что вывод в PHP не столь важен, сколько хорошенько понять прицип объединения таблиц... Когда например лучше применить одно, а когда другое. там когда INNER JOIN а когда LEFT JOIN или FULL OUTER JOIN и т.д ) - из за этого я плохо понимаю что я делаю, вот и решил разобраться...
Этот код я взял с вашего примера выше при создании таблиц. Этого я не указывал когда у себя создавал таблицы. Разве здесь нужны такие ключи? Сори если вопрос не очень корректный, в данный момент не очень хорошо разбираюсь в грамотной архитектуре MySQL. Только на базовом уровне.
Надеюсь я не надоел
EuGen
Отправлено: 30 Июля, 2013 - 14:26:26
Профессионал
Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007 Откуда: Berlin
Помог: 707 раз(а)
Внешние ключи нужны для контроля целостности данных на уровне СУБД (о чём свидетельствует, например, указанные мной ON DELETE SET NULL ON UPDATE CASCADE).
Если не получается именно одним циклом, то, хорошо, вот пример:
$rConnect=new mysqli('localhost','user','password','test') or exit(mysqli_error());
$rSelect=$rConnect->query('SELECT tbl20130730_parent.title AS category, tbl20130730_child.title AS item FROM tbl20130730_parent LEFT JOIN tbl20130730_child ON tbl20130730_child.parent_id=tbl20130730_parent.id ORDER BY tbl20130730_parent.id') or exit(mysqli_error());
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.