Я написал запрос, который содержит набор подзапросов:
SELECT
`board_id`,
`post_count`,
ROUND(`post_age_avg`, 3) as `post_age_avg`,
ROUND(`post_rating_avg`, 3) as `post_rating_avg`,
ROUND(`board_age`, 3) as `board_age`,
ROUND(1 - (`post_age_avg` / `board_age`), 3) AS `board_usage`,
ROUND((`post_count` / `board_age`) * `post_rating_avg`, 3) AS `board_rating`
FROM
(SELECT
`board_id`,
(SELECT COUNT(*) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`) AS `post_count`,
(SELECT AVG(TIME_TO_SEC(TIMEDIFF(NOW(), `post`.`created_on`)) / 3600) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`) as `post_age_avg`,
(SELECT AVG(`rating`) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`) AS `post_rating_avg`,
TIME_TO_SEC(TIMEDIFF(NOW(), `board`.`created_on`)) / 3600 AS `board_age`
FROM `board`) AS `board_stats`
Теперь, когда я более чем открыт для предложений по оптимизации или улучшению этого запроса, мой вопросотносится к тому, каким образом я мог бы сохранить этот запрос для будущего использования.
A view было бы здорово, однако согласно странице справочника MySQL по CREATE VIEW
:
- Оператор
SELECT
не может содержать подзапрос в предложении FROM
.
Итак, яинкапсулировал запрос в процедуру .Работает нормально, вызывая:
CALL get_board_stats();
Однако я быстро обнаружил, что существует ограниченная ( read zero ) гибкость использования процедур в отношении использования результатов в качестве подзапроса.Как и другие на SO с подобными вопросами, я обнаружил:
SELECT * FROM (CALL get_board_stats()) AS `board_stats`;
И любая их перестановка синтаксически неверна.
Так что мой вопрос таков;как я могу добиться (, если это вообще возможно ) сценария, в котором этот запрос может быть сохранен для последующего использования в качестве «виртуальной таблицы» в последующих запросах, позволяя сделать что-то вроде:
SELECT * FROM /* give_me_board_stats_somehow() */ WHERE ...
Ладно, @OMG Пони, это последняя версия, с которой я собираюсь ( на данный момент ), так как она производит идентичный набор результатов с тем же числовым значениемточность.Он очень похож на ваш, за исключением того, что я опустил JOIN
в пользу ( еще раз ) подзапросов, хотя на этот раз не как столбцы в производной таблице.Что-то подсказывает мне, что это менее эффективно ( по сравнению, например, с JOIN
решением ), возможно, вы можете пролить свет на это:
SELECT
`board`.`board_id`,
(SELECT COUNT(*) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`) AS `post_count`,
ROUND((SELECT AVG(TIME_TO_SEC(TIMEDIFF(NOW(), `post`.`created_on`)) / 3600) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`), 3) AS `post_age_avg`,
ROUND((SELECT AVG(`rating`) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`), 3) AS `post_rating_avg`,
ROUND(TIME_TO_SEC(TIMEDIFF(NOW(), `board`.`created_on`)) / 3600, 3) AS `board_age`,
ROUND(1 - ((SELECT AVG(TIME_TO_SEC(TIMEDIFF(NOW(), `post`.`created_on`)) / 3600) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`) / (TIME_TO_SEC(TIMEDIFF(NOW(), `board`.`created_on`)) / 3600)), 3) AS `board_usage`,
ROUND(((SELECT COUNT(*) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`) / (TIME_TO_SEC(TIMEDIFF(NOW(), `board`.`created_on`)) / 3600)) * (SELECT AVG(`rating`) FROM `post` WHERE `post`.`board_id` = `board`.`board_id`), 3) AS `board_rating`
FROM `board`
( Я бы выложил что-то лучше отформатированное, чем этот пакет, но Workbench украсит отстой большими запросами, и у меня нет усилий: P )
По какой-то причине ваше решение продолжалопредоставить неверные результаты для board_usage
и board_rating
.