Помогите переписать или исправить запрос. Есть три таблицы: 1-ая это категории, 2-ая ссылки, 3-я рейтинги ссылок. Нужно сделать выборку всех полей ссылок для определенной категории, а так же подсчитать среднее значение для рейтингов и отсортировать по рейтингам и дате создания ссылок. Запрос такой и он замечательно работает: [sql] SELECT `main_table`.*, `cat`.*, AVG(dlr_rating) AS `avg_rating` FROM `dx_linkexchange_links` AS `main_table` LEFT JOIN `dx_linkexchange_category` AS `cat` ON main_table.dll_dlc_id = cat.dlc_id LEFT JOIN `dx_linkexchange_rate` AS `rating` ON main_table.dll_id = rating.dlr_dll_id WHERE (cat.store_id = '1') AND (main_table.dll_dlc_id = '3') AND (main_table.dll_status = 2) GROUP BY `dll_id` ORDER BY `avg_rating` DESC, `dll_created_time` ASC; [/sql] После чего система сама (пишу на готовом движке) удаляет все выбираемые поля в запросе, подставляя COUNT(*), удаляет сортировку и лимит. Метод класса я изменить или переопределить не могу. Получается следующее: [sql] SELECT COUNT(*) FROM `dx_linkexchange_links` AS `main_table` LEFT JOIN `dx_linkexchange_category` AS `cat` ON main_table.dll_dlc_id = cat.dlc_id LEFT JOIN `dx_linkexchange_rate` AS `rat` ON main_table.dll_id = rat.dlr_dll_id WHERE (cat.store_id = 1) AND (main_table.dll_dlc_id = 3) AND (main_table.dll_status = 2) GROUP BY `dll_id`; [/sql] Запрос в данном случае возвращает 13 строк, а не число 13. Задача в том, что бы написать запрос, который вернул бы нужные поля для вывода, и после обработки (см.выше) вернул правильное число полей. Вот. Заранее всех благодарю.
Подскажите ещё, почему может не работать COUNT(), если сделать вложенный запрос типа: [sql] SELECT COUNT(*) FROM (SELECT `main_table`.*, `cat`.*, AVG(dlr_rating) AS `avg_rating` FROM `dx_linkexchange_links` AS `main_table` LEFT JOIN `dx_linkexchange_category` AS `cat` ON main_table.dll_dlc_id = cat.dlc_id LEFT JOIN `dx_linkexchange_rate` AS `rating` ON main_table.dll_id = rating.dlr_dll_id WHERE (cat.store_id = 1) AND (main_table.dll_dlc_id = 3) AND (main_table.dll_status = 2) GROUP BY `dll_id`) AS `tbl` [/sql] Возвращает 0.
Всем спасибо, разобрался сам. Заработало так: [sql] SELECT COUNT(*) FROM ( SELECT `main_table`.*, `cat`.*, AVG(dlr_rating) AS `avg_rating` FROM `dx_linkexchange_links` AS `main_table` LEFT JOIN `dx_linkexchange_category` AS `cat` ON main_table.dll_dlc_id = cat.dlc_id LEFT JOIN `dx_linkexchange_rate` AS `rating` ON main_table.dll_id = rating.dlr_dll_id WHERE (cat.store_id = '1') AND (main_table.dll_dlc_id = '3') AND (main_table.dll_status = 2) GROUP BY `dll_id` ORDER BY `avg_rating` DESC, `dll_created_time` ASC) As `tbl`;[/sql] Т.е. при наличии сортировки. Вот. Если кто объяснит почему, буду очень благодарен.
разбираться лениво. пока вопрос - зачем во вложенном запросе выбираются все поля, да еще не от одной таблицы?
armadillo К сожалению вся проблема в том, что данный запрос формируется посредством коллекции условий модели (кто работал на платформе Magento, тот должен быть в курсе), и для вывода списка с постраничной навигацией, необходим весь запрос целиком, т.е. он один на всё. В этом вся проблема. Но вы правы, абсолютно все данные мне не нужны, но это всего дополнительно три поля. Тогда следует вопрос, на сколько это ускорит выполнение запроса, если указать только необходимый перечень полей?
Да, действительно проверил опытным путём. Запрос с объединением выполнялся 94 ms - стал 62 ms. При подсчёте общего количества с вложенным запросом, был 62 ms - стал 15 ms Это действительно очень сильно ускорило выполнение скрипта. armadillo спасибо за совет. Я считаю, что вопрос можно закрывать. Спасибо всем, кто посмотрел и поучаствовал. )
конкретно для count можно и сам запрос заметно упростить. [sql]SELECT COUNT(distinct `dll_id`) FROM `dx_linkexchange_links` AS `main_table` JOIN `dx_linkexchange_category` AS `cat` ON main_table.dll_dlc_id = cat.dlc_id AND cat.store_id = '1' WHERE main_table.dll_dlc_id = '3' AND main_table.dll_status = 2[/sql] (LEFT для этого JOIN'а не нужен) у меня в пейджере предусмотрена возможность отдельного запроса именно поэтому. Такой запрос наверняка будет побыстрее, тем более чем сортировка по разным правилам. Что "оно работает при добавлении сортироки" - большие сомнения, не надо шаманить. Как оно организованно в твоем случае - я не вижу, ты читал это?
Ссылку, которую вы мне дали, я уже посмотрел. Но я работаю не на своей платформе. Система организованна на движке Magento (eCommerce Platform). Сам Magento использует Zend Framework. Для вывода списка с постраничной навигацией для frontend-a используется уже готовый блок (объект) (использование уже готовых (встроенных) решений - требование заказчика), который берет "коллекшен" (набор правил в виде методов объекта модели) и возвращает уже готовый результат. Это очень коротко. Если говорить русским языком - чистого SQL-я там нет и, если делать всё правильно, не должно быть. Всё через объекты. Только вот иногда случаются такие вот проблемки.
armadillo Да, вы правы, его можно сделать отдельно не используя текущий "колекшен", но это не совсем правильно. Если делать правильно, то я вообще не должен заморачиваться по поводу подсчёта, система сама должна правильно подсчитать. Точно подметил Mr.M.I.T. по поводу кривых SQL билдеров. Я могу привести цепочку логики, просто это уже не будет относиться к этой ветке форума: "Колекшен" в блоке: PHP: $collection = Mage::getResourceSingleton('linkexchange/links_collection') ->joinRating() ->addCategoryFilter($categoryId) ->addStatusFilter() ->addSortOrder(); $collection->addCount(); $this->setItems($collection); Вот из этого формируется SQL (кроме последней строки). Формируем блок для вывода пагинатора: PHP: $pager = $this->getLayout()->createBlock('page/html_pager', 'links.pager'); $pager->setCollection($this->getItems()); $this->setChild('pager', $pager); $this->getItems()->load(); Если описывать все правила, формирующее "колекшен" будет ещё 6 методов. Если желаете, могу и их бросить в ветку.
armadillo При написании отдельного запроса в модели, необходимо будет еще передавать туда ряд параметров, т.е. повторять уже реализованный на более низком уровне функционал. Это не совсем хорошо. Вы знаете, я проверил разницу в производительности между нашими решениями, она очень незначительна. Поэтому я решил ничего не менять.
Разница будет зависеть от кол-ва записей. но поскольку я так и не выяснил, куда ты вставляешь запрос и как он делается без этого, ничего сказать не могу.