Обработка связей MYSQL не возвращает правильных результатов
Я работаю с MYSQL и пытаюсь работать в рамках возможностей MYSQL связей для ранжирования.
мой запрос:
SELECT petz.s_name,
petz.breed,
a.num,
sum(a.rank) AS rank
FROM wins_conf a
JOIN
(SELECT DISTINCT rank
FROM wins_conf
ORDER BY rank DESC LIMIT 10) b ON a.rank = b.rank
JOIN petz ON a.num=petz.num
GROUP BY petz.num
ORDER BY petz.breed,
rank DESC
который возвращает результаты:
sum(Rank)
INSANITY'S ACE OF SPADES Collie 1026 58
INSANITY'S SAVE ME Collie 1000 31
STAR GAZER'S BEAUTIFUL LIES Collie 1039 24
BANYON'S ALL IS FORGIVEN Collie 1009 19
FELIXTOWE CHERRY BLOSSOM Collie 1214 18
KE'S PRICELESS FIGUREINE Collie 1004 13
NOVABLUE'S LOVES UNENDING LEGACY Collie 1211 12
STAR GAZER'S WARRIOR OF MY HEART Collie 1059 9
INSANITY'S BE MINE Collie 1028 9
STAR GAZER'S A WILDCAT'S REVENGE Collie 1040 5
KE'S TRICKS OF THE TRADE Collie 1005 5
запись 1059 (ЗВЕЗДНЫЙ ГАЗЕР-ВОИН МОЕГО СЕРДЦА) возвращает 9 в качестве ранга, однако это должно быть 12 на основе записей в БД, которые суммируются ()
Rank
conf 33 13 1059 Best of Breed 0 0 5 0 2
conf 78 3139 1059 Best of Breed 0 0 4 0 2
conf 82 2518 1059 Best of Breed 0 0 1 0 2
conf 81 13 1059 Best in Specialty0 0 1 0 2
conf 79 13 1059 Best of Breed 0 0 1 0 2
Проведя некоторые исследования, я обнаружил, что он будет видеть только последние 3 записи в sum() столбца ранга, если 1 больше или равен 4
Любые предложения о том, как это исправить?
РЕДАКТИРОВАТЬ / ОБНОВИТЬ в ответ на AgRizzo Я только что удалил полные имена и породы для облегчения чтения, это то, что я хочу, по рангу. Я хочу отображать ранги с дубликатами, но только 10 (включая их дубликаты).
num rank
1 1026 58
2 1000 31
3 1039 24
4 1009 19
4 1214 19
5 1004 13
6 1211 12
6 1059 12
7 1028 9
8 1005 5
8 1040 5
9 1010 3
10 1276 1
Я настраиваю некоторые основные данные здесь: http://sqlfiddle.com/ В нем отсутствует часть содержимого пуха, как показано выше, но это содержание не требуется в рейтинге.
3 ответа
Попробуй это
select petz.s_name, petz.breed, a.num, sum(a.rank) as rank
from wins_conf a
JOIN petz ON a.num=petz.num
GROUP BY petz.num
ORDER BY petz.breed, rank DESC LIMIT 10
Вот вариант с рейтингом
SELECT s_name
, breed
, num
, @denserank := IF(@prevrank = rank, @denserank, @denserank + 1 ) as DenseRank
, @prevrank := rank AS rank
FROM (
SELECT petz.s_name AS s_name
, petz.breed AS breed
, a.num AS num
, sum(a.rank) as rank
FROM wins_conf a
JOIN petz
ON a.num=petz.num
WHERE petz.breed = 'Collie'
GROUP BY petz.s_name, petz.breed, a.num
ORDER BY petz.breed, rank DESC) AS temp1
JOIN (SELECT @prevscore := NULL, @denserank := 0) AS dummy
WHERE @denserank < 5
Это здесь, на SQLFiddle http://sqlfiddle.com/. Из-за ваших ограниченных данных в этом примере перечислены 5 лучших, в противном случае выбираются все записи. Измените предложение WHERE, чтобы перечислить топ-10 на вашем сайте
В других RDBMS вы, возможно, использовали бы CTE для вычисления каждого petz
'общий балл (ваш SUM(rank)
), а затем функцию DENSE_RANK для ранжирования их в соответствии с этими оценками.
Поскольку в MySQL отсутствуют эти удобства, мы можем использовать VIEW или подзапросы вместо CTE. DENSE_RANK может быть вычислен с переменными сеанса, как в ответе @AgRizzo, или просто как один (1) плюс количество различных оценок "лучше", чем конкретная оценка.
Я собираюсь собрать все это с помощью VIEW, а не подзапросов, потому что я думаю, что это делает логику запроса очевидной:
SET SESSION sql_mode='ANSI';
-- Compute each petz' score
CREATE OR REPLACE VIEW scorez AS
SELECT "num", SUM("rank") AS "score"
FROM wins_conf
GROUP BY 1;
-- Compute each scored petz' DENSE_RANK
CREATE OR REPLACE VIEW standingz AS
SELECT my."num",
my."score",
COUNT(DISTINCT their."score") + 1 AS "rank" -- DENSE_RANK
FROM scores my
LEFT JOIN scores their
ON their.score > my.score
GROUP BY 1, 2;
-- Now fetch the full result set
SELECT standingz.rank, petz.*
FROM petz
INNER JOIN standingz
ON petz.num = standingz.num
ORDER BY standingz.rank ASC;