Класация

16 отговора 681 прегледа
#1

Класация

Привет :)
mySQL e базата, а това е новия ми проблем ...

таблица - Votes :

`id` int(11) unsigned NOT NULL auto_increment,
`voter_id` int(10) unsigned NOT NULL default '0',
`member_id` int(10) unsigned NOT NULL default '0',
`score` tinyint(2) unsigned NOT NULL default '0', (някакава оценка от 1 до 10)
`voted` datetime NOT NULL default '0000-00-00 00:00:00',
`host` varchar(23) NOT NULL default '',

Имам member_id и ми се иска само с SQL да изкарам на кое място е конкретния member според гласовете.

Значи в момента ползвам :
SELECT CAST(AVG(score) AS SIGNED INTEGER) AS score,member_id FROM votes GROUP BY member_id ORDER BY score DESC
и така получавам класация със средната оценка(точки от гласуването) и конкретния member; проблема ми е, че не знам как да взема реда, на който е примерно member_id - 25, т.е. ако след заявката имам набора -

score member_id
7.5 12
6 19
4.4 25
2 9

не знам как да разбера, че member_id 25 е на 3-то място. В MS SQL има rid (row id), което би ми свършило работа, но не знам дали има нещо такова тук. Друг вариант, който ми идва наум е трета колона, с променлива INT която от да 1 да инкрементира с всеки нов ред, но не знам как става манипулирането на тази променлива.

Мерси предварително за всички съвети :)

Отговор
в отговор на Cтyдeнт #2

Re: Класация

CREATE TEMPORARY TABLE result res_id TINYINT UNSIGNED PRIMARY KEY SELECT ... <твоята заявка>

salle.online.bg/sig
Отговор
в отговор на salle #3

Re: Класация

Друг начин:
SELECT @myRowNum := 0;
SELECT @myRowNum := @myRowNum +1,CAST(AVG(score) AS SIGNED INTEGER) AS score,10- score,member_id
FROM Votes GROUP BY member_id ORDER BY score DESC

Отговор
в отговор на _danitu #4

Re: Класация

Понеже твоя постинг ми е по-ясен и по-лесен ... но не бачка ... копвам го директно и ми дава грешката :
You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL 0 SELECT @myRowNum NULL @myRowNum +1,CAST(AVG(score) AS ...
При теб това наистина ли работи ? Аз съм 4.0.18, да не би да трябва някаква настройка да сменя ? Струва ми се, че така ще стане супер бързо и елегантно ... :)

Отговор
в отговор на _danitu #5

явно трябва да прегледам по-сериозно хелпа ;)

Явно трябва първо да се сетне променливата ...
SET @a = 0;
SELECT @a+1 as pos,CAST(AVG(score) AS SIGNED INTEGER) AS score,member_id
FROM votes GROUP BY member_id ORDER BY score DESC;

Това ми връща каквото ми трябва, но всички полета в колоната pos са 1 ...
SET @a = 0;
SELECT @a:= @а+1 as pos,CAST(AVG(score) AS SIGNED INTEGER) AS score,member_id
FROM votes GROUP BY member_id ORDER BY score DESC;

ми дава грешката -
You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '+1 as pos,CAST(AVG(score) AS SIGNED INTEGER) AS score,member_id

:(( тествах променливата самостоятелно и също си бачка, но нещо инкрементацията не се получава. Как да я подкарам ?

Отговор
в отговор на Cтyдeнт #6

Re: явно трябва да прегледам по-сериозно хелпа ;)

Това
SELECT @myRowNum := 0;
SELECT @myRowNum := @myRowNum +1,CAST(AVG(score) AS SIGNED INTEGER) AS score,member_id
FROM Votes GROUP BY member_id ORDER BY score DESC;
работи на 4.0.20

Пробвай тогава както ти казва salle, с временна таблица.
Отново пробвам на 4.0.20 обаче:

CREATE TEMPORARY TABLE test (a INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (a), KEY(score))
SELECT CAST(AVG(score) AS SIGNED INTEGER) AS score,member_id
FROM Votes GROUP BY member_id ORDER BY score DESC;

SELECT * FROM test; за да си видиш резултата после
и не забравяй DROP TABLE test; след като си свършиш работата с нея.

Отговор
в отговор на _danitu #7

Re: Не е задължително ..

TEMPORARY може и да не се трие. Като затвориш сесията тя си изчезва така или иначе. "По-чисто" е е стествено да се трие де.

salle.online.bg/sig
Отговор
в отговор на Cтyдeнт #8

Re: Защо ти е този CAST?

CAST(AVG( ...))

Не е ли по-логично да използваш ROUND() или FLOOR() ако целта ти е да закръгляваш?

salle.online.bg/sig
Отговор
в отговор на salle #9

Re: Защо ти е този CAST?

Ами може и да си прав, просто помня, че когато търсех веднъж AVG за нещо, което няма стойности и AVG ми даде NULL ... и с CAST го направих на 0 ... сигурно си прав, че FLOOR е за предпочитане; ще пробвам с него :)

Отговор
в отговор на salle #10

Защо не коментираш това ?

Защо не коментираш манипулирането на променливата ? Не е ли това по-лесното решение за моя проблем ? Защо с временна таблица да става по-лесно като може просто една променлива да показва номера на реда ? Защо при мен не работи, а при госпожицата работи ?

Отговор
в отговор на Cтyдeнт #11

Re: Защо ти е този CAST?

AVG() от NULL трябва да върне NULL защото иначе ще изкриви резултата. NULL е "неизвестна стойност" а средно аритметично от неизвестни стойности няма как да е нещо известно нали така?

Освен това NULL като нещо неизвестно няма и тип. Съответно
mysql> SELECT CAST(NULL AS SIGNED);
+----------------------+
| CAST(NULL AS SIGNED) |
+----------------------+
| NULL |
+----------------------+


с CAST няма да промениш типа на NULL защото няма нищо за променяне

salle.online.bg/sig
Отговор
в отговор на Cтyдeнт #12

Re: А защо да го коментирам?

Пронципно не харесвам този трик с променливите защото по този начин резултатът от заявката започва да зависи от реда в който редовете се съхраняват и реда в който се обработват а това по принцип е недопустимо според релационния модел. Резултатът трябва винаги да еднакъв независимо от физическата подредба.

salle.online.bg/sig
Отговор
в отговор на salle #13

Я пак ;)

Хм ... аз съм с 4.0.18 и при мен
SELECT CAST(null AS SIGNED) си дава точно нула :) Такава е и логиката ми - ако за някой няма гласове в таблицата, то AVG() трябва да ми даде точно 0.

Отговор
в отговор на salle #14

Re: Не е задължително ..

"TEMPORARY може и да не се трие........"
Знам, ама предпочитам да си ги трия веднага, вместо да следя дали не им слагам еднакви имена.

Отговор
в отговор на Cтyдeнт #15

Ми да и не

Щото ползвам libmysql, ама леко модифицирани.
И като кажа каквото имам да казвам, пък то ми върне NULL, а аз съм поискал резултата не като стринг а като инт - ми получавам 0.
Щото atoi("NULL") връща нула.
Точно както и atoi("КРЕТЕН") или atoi("БИРА") - все 0 връща.
Искал съм инт - получавам инт.

Bеer? Mоre?
Плацебото
Отговор
в отговор на Cтyдeнт #16

Re: Бъг :)

Това е бъг в 4.0 който е оправен в 4.1

Логиката ти може и да е коректна според теб, но по-добре да не разчиташ на бъгове а да действаш явно:

SELECT IFNULL(AVG(score))
или
SELECT IF(COUNT(score) = 0, 0, AVG(score))

salle.online.bg/sig
Отговор
в отговор на salle #17

:)

Това е друго вече :) Хем го разбрах, хем е чисто :) Мерси...

Отговор