Сортировка по рейтингам в базе данных - куда этот SQL ставить? (PHP / MySQL) - PullRequest
2 голосов
/ 23 февраля 2010

ОК - я сразу перейду к делу - вот вопрос PHP-кода:

<h2>Highest Rated:</h2>

    <?php 

        // Our query base               
        $query = $this->db->query("SELECT * FROM code ORDER BY rating DESC");

        foreach($query->result() as $row) {
    ?>  
        <h3><?php echo $row->title." ID: ";echo $row->id; ?></h3>
            <p class="author"><?php  $query2 = $this->db->query("SELECT email FROM users WHERE id = ".$row->author);
echo $query2->row('email');?></p>
            <?php   echo ($this->bbcode->Parse($row->code)); ?>

        <?php } ?>

Извините, это немного грязно, это все еще черновик. Во всяком случае, я исследовал способы использования системы Ratings - ранее у меня было одно поле 'rating', как вы можете видеть по SELECT * FROM кода ORDER BY rating DESC. Однако я быстро понял, что рассчитать такие средние значения было невозможно, поэтому я создал пять новых столбцов - рейтинг1, рейтинг2, рейтинг3, рейтинг4, рейтинг5. Итак, когда 5 пользователей оценивают что-то 4 звезды, rating4 говорит 5 ... это имеет смысл? В каждом столбце ratingx указывается количество раз, когда был присвоен рейтинг.

Так или иначе: у меня есть этот оператор SQL:

SELECT id, (ifnull(rating1,0) + ifnull(rating2,0) + ifnull(rating3,0) + ifnull(rating4,0) + ifnull(rating5,0)) / ((rating1 IS NOT NULL) + (rating2 IS NOT NULL) + (rating3 IS NOT NULL) + (rating4 IS NOT NULL) + (rating5 IS NOT NULL)) AS average FROM code

Снова грязно, но эй. Теперь мне нужно знать, как я могу включить этот оператор SQL в мой скрипт? В идеале вы могли бы подумать, что общий запрос будет «ВЫБРАТЬ * ИЗ КОДА ORDER BY ( этот действительно длинный запрос, который я только что сформулировал ) DESC», но я не совсем понимаю, как это работает ... как мне это сделать? Это? Запрос, сохранить результат в переменной, что-то вроде этого?

Если это не имеет смысла, извините! Но я очень ценю помощь :)

Jack

Ответы [ 5 ]

6 голосов
/ 23 февраля 2010

Вы должны полностью вернуться к чертежной доске.

<?php
$query = $this->db->query("SELECT * FROM code ORDER BY rating DESC");
foreach($query->result() as $row) {
    $this->db->query("SELECT email FROM users WHERE id = ".$row->author;
}

В любое время вы видите это в своем коде, немедленно прекратите то, что вы делаете. Это то, что объединяет. Вы почти никогда не хотите зацикливаться на результатах запроса и выдавать несколько запросов из этого цикла.

SELECT code.*, users.email 
FROM code
JOIN users ON users.id = code.author
ORDER BY rating DESC

Этот запрос будет собирать все эти данные в одном наборе результатов, что устраняет проблему запроса N + 1.

Я не отвечу на остальную часть вашего вопроса, пока вы не очистите свой вопрос и не объясните, что вы пытаетесь сделать.

2 голосов
/ 23 февраля 2010

если вы хотите изменить таблицы снова, вот мое предложение:

почему бы вам не хранить два столбца: RatingTotal и RatingCount, каждый пользователь, который оценивает его, будет увеличивать RatingCount на единицу и всеони голосуют (5,4,4.2 и т. д.) и добавляются в RatingTotal.Затем вы можете просто заказать ORDER BY RatingTotal / RatingCount

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

1 голос
/ 23 февраля 2010

Некоторые отличные идеи, но я думаю, что лучший способ (поскольку сидерик сказал, что тяжелее писать, а писать тяжелее) будет иметь рейтинг столбцов и times_rated, и просто сделать что-то вроде этого:* current_rating - рейтинг, применяемый, когда человек нажимает на маленькие звездочки.Это просто взвешивает рейтинг текущего пользователя в среднем с текущим рейтингом.

1 голос
/ 23 февраля 2010

Вы должны включить его в часть SELECT:

SELECT *, (if ....) AS average FROM ... ORDER BY average

Редактировать: при условии, что ваше утверждение ifnull действительно работает ...

Возможно, вы также захотитеизучать объединения, чтобы избежать повторного запроса к базе данных для каждого пользователя;Вы можете сделать все в одном утверждении.

Кроме того, я бы также сказал, что вам нужно только одно среднее число и общее количество голосов, которые должны предоставить вам всю необходимую информацию.

1 голос
/ 23 февраля 2010

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

Другие опции:

  • Попробуйте упорядочить по вычисленному имени столбца «среднее». SQL Server поддерживает это. , не уверен насчет mysql.
  • Используйте вид. Вы можете создать представление на своей базовой таблице, которое выполняет для вас среднее вычисление, и вы можете запросить его.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...