Класация
16 отговора
681 прегледа
Класация
Привет :)
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 да инкрементира с всеки нов ред, но не знам как става манипулирането на тази променлива.
Мерси предварително за всички съвети :)
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 да инкрементира с всеки нов ред, но не знам как става манипулирането на тази променлива.
Мерси предварително за всички съвети :)
Re: Класация
CREATE TEMPORARY TABLE result res_id TINYINT UNSIGNED PRIMARY KEY SELECT ... <твоята заявка>
salle.online.bg/sig
salle.online.bg/sig
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
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
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, да не би да трябва някаква настройка да сменя ? Струва ми се, че така ще стане супер бързо и елегантно ... :)
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, да не би да трябва някаква настройка да сменя ? Струва ми се, че така ще стане супер бързо и елегантно ... :)
явно трябва да прегледам по-сериозно хелпа ;)
Явно трябва първо да се сетне променливата ...
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
:(( тествах променливата самостоятелно и също си бачка, но нещо инкрементацията не се получава. Как да я подкарам ?
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
:(( тествах променливата самостоятелно и също си бачка, но нещо инкрементацията не се получава. Как да я подкарам ?
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; след като си свършиш работата с нея.
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; след като си свършиш работата с нея.
Re: Не е задължително ..
TEMPORARY може и да не се трие. Като затвориш сесията тя си изчезва така или иначе. "По-чисто" е е стествено да се трие де.
salle.online.bg/sig
salle.online.bg/sig
Re: Защо ти е този CAST?
CAST(AVG( ...))
Не е ли по-логично да използваш ROUND() или FLOOR() ако целта ти е да закръгляваш?
salle.online.bg/sig
Не е ли по-логично да използваш ROUND() или FLOOR() ако целта ти е да закръгляваш?
salle.online.bg/sig
Re: Защо ти е този CAST?
Ами може и да си прав, просто помня, че когато търсех веднъж AVG за нещо, което няма стойности и AVG ми даде NULL ... и с CAST го направих на 0 ... сигурно си прав, че FLOOR е за предпочитане; ще пробвам с него :)
Защо не коментираш това ?
Защо не коментираш манипулирането на променливата ? Не е ли това по-лесното решение за моя проблем ? Защо с временна таблица да става по-лесно като може просто една променлива да показва номера на реда ? Защо при мен не работи, а при госпожицата работи ?
Re: Защо ти е този CAST?
AVG() от NULL трябва да върне NULL защото иначе ще изкриви резултата. NULL е "неизвестна стойност" а средно аритметично от неизвестни стойности няма как да е нещо известно нали така?
Освен това NULL като нещо неизвестно няма и тип. Съответно
mysql> SELECT CAST(NULL AS SIGNED);
+----------------------+
| CAST(NULL AS SIGNED) |
+----------------------+
| NULL |
+----------------------+
с CAST няма да промениш типа на NULL защото няма нищо за променяне
salle.online.bg/sig
Освен това NULL като нещо неизвестно няма и тип. Съответно
mysql> SELECT CAST(NULL AS SIGNED);
+----------------------+
| CAST(NULL AS SIGNED) |
+----------------------+
| NULL |
+----------------------+
с CAST няма да промениш типа на NULL защото няма нищо за променяне
salle.online.bg/sig
Re: А защо да го коментирам?
Пронципно не харесвам този трик с променливите защото по този начин резултатът от заявката започва да зависи от реда в който редовете се съхраняват и реда в който се обработват а това по принцип е недопустимо според релационния модел. Резултатът трябва винаги да еднакъв независимо от физическата подредба.
salle.online.bg/sig
salle.online.bg/sig
Я пак ;)
Хм ... аз съм с 4.0.18 и при мен
SELECT CAST(null AS SIGNED) си дава точно нула :) Такава е и логиката ми - ако за някой няма гласове в таблицата, то AVG() трябва да ми даде точно 0.
SELECT CAST(null AS SIGNED) си дава точно нула :) Такава е и логиката ми - ако за някой няма гласове в таблицата, то AVG() трябва да ми даде точно 0.
Re: Не е задължително ..
"TEMPORARY може и да не се трие........"
Знам, ама предпочитам да си ги трия веднага, вместо да следя дали не им слагам еднакви имена.
Знам, ама предпочитам да си ги трия веднага, вместо да следя дали не им слагам еднакви имена.
Ми да и не
Щото ползвам libmysql, ама леко модифицирани.
И като кажа каквото имам да казвам, пък то ми върне NULL, а аз съм поискал резултата не като стринг а като инт - ми получавам 0.
Щото atoi("NULL") връща нула.
Точно както и atoi("КРЕТЕН") или atoi("БИРА") - все 0 връща.
Искал съм инт - получавам инт.
Bеer? Mоre?
Плацебото
И като кажа каквото имам да казвам, пък то ми върне NULL, а аз съм поискал резултата не като стринг а като инт - ми получавам 0.
Щото atoi("NULL") връща нула.
Точно както и atoi("КРЕТЕН") или atoi("БИРА") - все 0 връща.
Искал съм инт - получавам инт.
Bеer? Mоre?
Плацебото
Re: Бъг :)
Това е бъг в 4.0 който е оправен в 4.1
Логиката ти може и да е коректна според теб, но по-добре да не разчиташ на бъгове а да действаш явно:
SELECT IFNULL(AVG(score))
или
SELECT IF(COUNT(score) = 0, 0, AVG(score))
salle.online.bg/sig
Логиката ти може и да е коректна според теб, но по-добре да не разчиташ на бъгове а да действаш явно:
SELECT IFNULL(AVG(score))
или
SELECT IF(COUNT(score) = 0, 0, AVG(score))
salle.online.bg/sig