Перейти к содержанию
СофтФорум - всё о компьютерах и не только

Сложный запрос в MySQL


Рекомендуемые сообщения

Имеется 2 таблицы:

CREATE TABLE `downloads_categories` (`cid` int(11) NOT NULL auto_increment,`title` varchar(50) NOT NULL default '',`cdescription` text NOT NULL,`parentid` int(11) NOT NULL default '0',PRIMARY KEY (`cid`),KEY `cid` (`cid`),KEY `title` (`title`))downloads_categories` VALUES (1, 'Программы', '', 0);downloads_categories` VALUES (2, 'Графика и дизайн', '', 1);downloads_categories` VALUES (3, 'Графика', '', 0);downloads_categories` VALUES (4, 'Сканы', '', 3);downloads_categories` VALUES (5, 'Иконки и смайлики', '', 3);downloads_categories` VALUES (6, 'Анимация GIF', '', 3);

И вторая таблица с самими файлами, где есть тоже CID (к какой категории файл относится).

В таблице для котегорий, если PARENTID - это категория в которую входит подкатегория, если PARENTID=0, то соотв. она главная.

Если мы смотрим подкатегорию, например Иконки и смайлики, то тут просто, делаем запрос в файлы и показываем все файлы CID которых = 5.

Мне хочется сделать, чтобы если смотрим главную категорию, например Графика, то показывались все файлы, которые входят в ее подкатегории. Вот тут и запутался.

Нужно если PARENTID=0, то зная CID нужно запросить все категории, PARENTID которых ровняется этому CID (на данном примере 4,5,6) а затем зная CID этих подкатегорий, запросить все файлы, которые соответсвуют им.

Сказали что можно как то сделать через сложный запрос LEFT JOIN.

У меня есть пример такого запроса, но там в другом применении немного.

---

На всякий случай PHP 4, движок PHP-Nuke.

Ссылка на комментарий
Поделиться на другие сайты

Зачем здесь left join...

Если таблица с файлами выглядит так:

CREATE TABLE `files` (`fid` int(11) NOT NULL auto_increment,`cid` varchar(50) NOT NULL default '',`file_name` varchar(255) NOT NULL,PRIMARY KEY (`fid`),KEY `cid` (`cid`))

То запрос

select file_name from files f, downloads_categories dc where f.cid = dc.cid and dc.parentid=3

выберет все файлы, которые относятся к подразделам первого колена раздела с cid=3 (Графика)

Ссылка на комментарий
Поделиться на другие сайты

Shurr:

Я такой запрос и невидел никогда. Но работает :(

Сейчас буду мудрить с остальным :)

Спасибо ГРОМАДНОЕ! :)

Ссылка на комментарий
Поделиться на другие сайты

Еще вот вопросик.

Можно ли усложнить запрос, чтобы вытаскивая файлы еще отображались их категории.

Было например так:

---

Файл 1

Раздел: Графика. Подраздел: Иконки и смайлики.

---

Файл 1

Раздел: Графика. Подраздел: Анимация GIF.

---

Поля title совпадают в обеих таблицах, но соотв. разные, в категориях - название категории, в файла - название файла.

Ссылка на комментарий
Поделиться на другие сайты

Поля title совпадают в обеих таблицах, но соотв. разные, в категориях - название категории, в файла - название файла.

В смысле поле, которое я назвал `file_name` у тебя называется title?

select f.title, f.cid, dc.title, dc.cdescription from files f, downloads_categories dc where f.cid = dc.cid and dc.parentid=3

Если ты обращаешься к результирующим полям по имени а не по порядковому номеру, и поэтому тебя смущает то, что два поля имеют одинаковое имя - им можно дать псевдонимы:

select f.title as file_name, f.cid, dc.title as category_name, dc.cdescription from files f, downloads_categories dc where f.cid = dc.cid and dc.parentid=3

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

Ссылка на комментарий
Поделиться на другие сайты

Еще раз спасибо!

С главной категорей все.

С подкатегориями проще, но там 2 запроса получается.

Нам известно изначально PARENTID (запрос идет в самом начале, чтобы узнать категория или подкатегория). Известен и CID

Запрашиваем все файлы из подкатегории по CID и все.

А чтобы узнать какая главная категория, нужно зная ее PARENTID запросить ее название.

В такой же один запрос можно сделать? Чтобы запросить из таблицы для файлов все CID, а из таблицы для категорий запросить TITLE по PARENTID.

Поидеи можно сделать и вручную :blush2: категорий главных всего штук 5 будет, можно и условием сделать:

IF CID=1

$cat = "Программы"

Ссылка на комментарий
Поделиться на другие сайты

Насчет синтаксиса MySQL не знаю, но в Interbase делается так:

SELECT f.title, cat.title, parent.title  FROM files f  JOIN downloads_categories cat	 ON cat.cid = f.cid  JOIN downloads_categories parent	 ON parent.cid = cat.parentid  WHERE cat.parentid=3

либо собрав все в кучу

SELECT f.title, cat.title, parent.title  FROM files f, downloads_categories cat, downloads_categories parent  WHERE cat.cid = f.cid AND parent.cid = cat.parentid AND cat.parentid=3

Только нужно добавить корневой объект с cid=0 для запросов с категорией у которой parentid=0

Изменено пользователем Ramzes_
Ссылка на комментарий
Поделиться на другие сайты

Ramzes_:

С основным каталогом все получилось.

Насколько я понял это запрос для него, хотя могу ошибаться...

У меня такая последовательность:

Когда заходишь в категорию, идет запрос в базу где проверяется PARENTID.

Далее идет условие, если PARENTID=0, то это значит главная категория.

Затем идет запрос, который сказал Shurr.

Выводятся все файлы подкатегорий.

Если PARENTID не равно 0, то там просто.

Обычный запрос где CID файлов = CID подкатегории, в которой находишься.

И файлы выводятся.

К тому же PARENTID и заголовок подкатегории нам известно из первого запроса (до условия).

Не хватает только одного, названия главной категории, PARENTID ее есть, но нет названия.

1 вариант - еще раз сделать запрос

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

3 вариант - незнаю. Это сразу вывести файлы и заодно узнать в категориях название.

Ссылка на комментарий
Поделиться на другие сайты

Ну, во-первых, ты можешь сделать так, как показал Ramzes_.

Во-вторых, все данные об основной категории ты можешь узнать еще в том запросе, в котором запрашиваешь ее PARENTID. Это позволит тебе избавиться от одного join'a.

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

Ссылка на комментарий
Поделиться на другие сайты

Shurr:

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

А такой пример не приведешь?

Сейчас у меня просто:

SELECT title,parentid FROM downloads_categories WHERE cid='$cid'

Ссылка на комментарий
Поделиться на другие сайты

У тебя же уже есть в выборке title.

Вот и используй его. Если надо - добавь еще cdescription...

SELECT title, parentid, cdescription FROM downloads_categories WHERE cid='$cid'

P.S. Почитал бы ты какую-нибудь литературку по SQL... Дело не в том, что мне лень отвечать - это не сложно. Просто очень похоже, что с SQLем ты ознакомился исключительно по примерам, без теории. Тебе самому будет гораздо проще, если ты будешь знать возможности инструмента с которым работаешь.

Ссылка на комментарий
Поделиться на другие сайты

Shurr:

Эти данные я и так использую, но этот запрос выводит:

(4, 'Сканы', '', 3);

Имеем название подкатегории и PARINTID категории, а нужно еще название категории. (чтобы использовалась наверху странички и в самих файлах)

(4, 'Сканы', '', 3) 3=Графика

И получить:

$podcateg = Сканы

$parentid = 3

$categ = Графика

--------------

Можно так:

SELECT title, parentid FROM downloads_categories WHERE cid='$cid'

SELECT title FROM downloads_categories WHERE cid='$parentid'

Есть ли какая нибудь разница 2 запроса или в впихать 1 ? (с точки зрения нагрузки и т.д.)

--------------

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

Ты прав, с PHP и MySQL я знаком только по примерам, смотрю как сделано в одном модуле и точно так же делаю в другом. Подгоняю методом научного втыка, пока не получится.

А если сталкиваюсь с таким, когда примера нет, то и застрял как тут.

Теперь вот имея примеры таких запросов, упрощу пару модулей, чтобы уменьшить запросы в БД или вывести подругому данные.

Изменено пользователем Alexander-V-Sh
Ссылка на комментарий
Поделиться на другие сайты

Alexander-V-Sh

Что-то я совсем запутался. ;)

Смотри, тебе приходит id категории. Ты делаешь запрос:

SELECT title, parentid FROM downloads_categories WHERE cid='$cid'

Допустим id категории равен 3, тогда результат такой:

title = Графика, parentid = 0

Далее ты смотришь, если parentid=0, то:

select f.title as file_name, f.cid, dc.title as category_name from files f, downloads_categories dc where f.cid = dc.cid and dc.parentid=3

Допустим ты имеешь такой результат:

file_name = file1, cid = 4, category_name = Сканы

file_name = file2, cid = 4, category_name = Сканы

file_name = file3, cid = 5, category_name = Иконки и смайлики

file_name = file4, cid = 5, category_name = Иконки и смайлики

file_name = file5, cid = 6, category_name = Анимация GIF

file_name = file6, cid = 6, category_name = Анимация GIF

Имя раздела, Графика, ты узнал в первом запросе, оно общее для всех файлов, которые ты будешь выводить. Имя файла, cid подраздела и имя раздела у тебя есть в результате второго запроса.

Чего тебе еще не хватает?

Ссылка на комментарий
Поделиться на другие сайты

Shurr:

Вот смотри ;)

Человек заходит по сслыке, где CID равна 3,4,5 и т.д.

Идет запрос в базу, где уточняется, раздел это или подраздел, заодно вынимаем title.

После этого запроса получаем:

$title

$parentid

Стоит условие, если parentid = 0, то это раздел и:

SELECT d.lid, d.title as file_name, d.description, d.date, d.hits, d.totalcomments, d.filesize, d.version, d.homepage, dc.title as category_name, dc.cid as podcategory_name FROM ".$prefix."_downloads_downloads d, ".$prefix."_downloads_categories dc where d.cid = dc.cid and dc.parentid='$cid' order by $orderby limit $min,$perpage

И выводим все файлы, которые входят во все подкатегории.

А $title из первого запроса - стоит после слова Раздел: $title

Это я сделал, за что большое спасибо. (как раз самое сложное)

Если parentid не равно 0, то это подраздел и такой запросище делать нет необходимости.

Там просто:

SELECT lid, title, date, hits, totalcomments FROM ".$prefix."_downloads_downloads WHERE cid='$cid' order by $orderby limit $min,$perpage

И выводим все файлы из подкатегории.

А $title из первого запроса у нас уже как Подраздел : $title

Но нет названия Раздела, в которую входит подраздел, есть только его parentid.

---

Тут вот проще всего - это еще раз сделать запрос и вынуть title главной категории

SELECT title FROM ".$prefix."_downloads_categories WHERE cid='$parentid'

Отдельный вопрос: В этом случае получится 2 простых запроса (вынуть только 1 значение с базы). Стоит ли в таких случаях обьединять их сложным запросом (с целью оптимизации) или 2 запроса ничуть не хуже?

Можно сделать кодом в данном случае. Категорий главных всего штук 5 и изменяться они врядли будут.

Если $parentid=4, $name = Программы

Если $parentid=6, $name = Графика

Если $parentid=8, $name = Книги

И все, никакого запроса в базу.

А вот если разумнее всего в этом случае будет обьединить запросы в 1, или в первом (когда определяется parentid) или во 2, когда выводятся файлы. То вот тут и незнаю как.

Если 2 простых ничуть не хуже 1 сложного, то я запрошу еще раз базу для заголовка главной категории и все ;) В код категории писать тоже не хочется.

Изменено пользователем Alexander-V-Sh
Ссылка на комментарий
Поделиться на другие сайты

ИМХО проще будет модифицировать первый запрос, чтобы он выбирал не только parentid, но и его title, если таковой имеется.

SELECT dc.title, dc.parentid, dc.cdescription, pdc.title as parent_title FROM downloads_categories dc left join downloads_categories pdc on dc.parentid=pdc.cid WHERE dc.cid='$cid'
Ссылка на комментарий
Поделиться на другие сайты

Shurr:

Вот теперь все. Спасиб :blush2:

Теперь сами файлы подредактирую аналогично, чтобы категории, подкатегории и сами файлы в 1 запрос уместить.

И пример будет под рукой, если потребуется в других модулях применить. (а то некоторые циклются до 50-100 запросов в бд, когда можно в 1 уместить)

Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...