SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 21.11.2011 17:37:28

Фяшя
Участник
Зарегистрирован: 22.02.2011
Сообщений: 11

Очень сложный запрос SELECT для выбора Рейтинга

Есть таблица истории побед в игре

CREATE TABLE IF NOT EXISTS `championat_history` (
  `uid` int(11) NOT NULL,
  `id` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'время записи',
  `reopen` int(11) NOT NULL,
  UNIQUE KEY `uid` (`uid`,`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;



и еще есть таблица с именами и аватарами пользователей

CREATE TABLE IF NOT EXISTS `championat_users` (
  `uid` int(11) NOT NULL,
  `ava` int(11) NOT NULL,
  `name` varchar(200) CHARACTER SET utf8 NOT NULL DEFAULT 'Некий пользователь',
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;



в ней
uid                id        status        time время записи       
42433684        18001        -1        2011-11-14 16:25:05       
42433684        16662        -1        2011-11-14 16:26:18       
42433684        774            1        2011-11-14 16:26:40       
6157046        18215        -1        2011-11-14 16:33:35       
6157046        2019            1        2011-11-14 16:33:39       


Нужно вывести следующие данные для каждого пользователя
Баллы подсчитываются из ячейки status , учитывая только положительные значения (т.е. where status=1)   

1) Пользователь   
2) Имя
3) Аватар

4) Сумма баллов   
5) место в таблице     за все время   
6) место в таблице     не учитывая сегодня

7) Сумма баллов    за неделю
8) место в таблице     за эту неделю
9) место в таблице     за прошлую неделю

10) Сумма баллов     за месяц
11) место в таблице     за этот месяц
12) место в таблице     за прошлый месяц

11) Сумма баллов     за год
12) место в таблице     за этот год
13) место в таблице     за прошлый год


То есть должна выводиться табличка с 13 ячейками и длинна регулироваться Limit`ом



Я неделю бьюсь над этим и уже почти обезнадежился.. Помогите ПЛИЗЗЗЗЗ!!!


Прикрепленные файлы:
Attachment Icon Безымянный.JPG, Размер: 101,568 байт, Скачано: 508

Неактивен

 

#2 21.11.2011 21:26:07

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Очень сложный запрос SELECT для выбора Рейтинга

Если Вы хотите сделать это всё одним запросом, то без подзапросов не обойтись.
Т.е. бежать по users и для каждого пользователя выбирать каждое поле отдельным
подзапросом.

Неактивен

 

#3 21.11.2011 23:58:25

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Очень сложный запрос SELECT для выбора Рейтинга

Вот вам набросок с первыми примерами, дальше аналогично.

select `all`.uid,`all`.cnt,`exclude_today`.cnt,`last_week`.cnt from
  (select uid,count(uid) cnt from championat_history where `status`=1 group by uid) `all`
left join
  (select count(uid) cnt from championat_history where `status`=1
   and DATE(FROM_UNIXTIME(`time`))!=CURDATE() group by uid) `exclude_today`
  on(all.uid=`exclude_today`.uid)
left join
  (select count(uid) cnt from championat_history where `status`=1
   and FROM_UNIXTIME(`time`)>NOW()-INTERVAL 1 WEEK group by uid) `last_week`
  on(all.uid=`last_week`.uid)

Отредактированно evgeny (22.11.2011 00:01:29)

Неактивен

 

#4 22.11.2011 10:49:03

Фяшя
Участник
Зарегистрирован: 22.02.2011
Сообщений: 11

Re: Очень сложный запрос SELECT для выбора Рейтинга

Большое спасибо!
Но этот код возвращает только Набранные очки за все время, за все время кроме сегодня, за прошлую неделю...
НО не показывает как получать номера позиции в таблице ( то есть если он за неделю наборал больше всех баллов - то еще 1 ячейка нужна last_week_pos в которой будет 1 \*первое место*\)


select
`all`.uid as uid,
`all`.cnt as alles,  
`exclude_today`.cnt as exclude_today,  
`last_week`.cnt     as last_week    
from
  (select uid,count(uid) cnt from championat_history where `status`=1 group by uid) `all`
left join
  (select count(uid) cnt,uid from championat_history where `status`=1
   and DATE((`time`))!=CURDATE() group by uid) `exclude_today`
  on(all.uid=`exclude_today`.uid)
left join
  (select count(uid) cnt,uid from championat_history where `status`=1
   and (`time`)>NOW()-INTERVAL 1 WEEK group by uid) `last_week`
  on(all.uid=`last_week`.uid)
 



Еще раз спасибо!!!!!!!!!!!!!!

Неактивен

 

#5 22.11.2011 12:53:10

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6757

Re: Очень сложный запрос SELECT для выбора Рейтинга

Сделайте еще одну (временную?) табличку, в которую посчитайте места
людей за прошлую неделю / месяц. Одним подзапросом это уже не сделаешь.

Неактивен

 

#6 22.11.2011 12:57:53

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Очень сложный запрос SELECT для выбора Рейтинга

Вот можно сделать по такому принципу.
Запрос не запускал, возможно есть синтаксические ошибки.


SELECT
`all`.uid AS uid,
`all`.cnt AS alles,  
`all`.pos AS all_pos,  
`exclude_today`.cnt AS exclude_today,  
`last_week`.cnt  AS last_week    
FROM (
SELECT a.*,(@pos:=@pos+1) pos  FROM
    (SELECT uid,COUNT(uid) cnt FROM championat_history WHERE `status`=1 GROUP BY uid ORDER BY cnt DESC) a,(select @pos:=0) z
) `all`
LEFT JOIN
  (SELECT COUNT(uid) cnt,uid FROM championat_history WHERE `status`=1
   AND DATE((`time`))!=CURDATE() GROUP BY uid) `exclude_today`
  ON(all.uid=`exclude_today`.uid)
LEFT JOIN
  (SELECT COUNT(uid) cnt,uid FROM championat_history WHERE `status`=1
   AND (`time`)>NOW()-INTERVAL 1 WEEK GROUP BY uid) `last_week`
  ON(all.uid=`last_week`.uid)



Подправил немного.

Отредактированно evgeny (22.11.2011 13:52:35)

Неактивен

 

#7 22.11.2011 15:16:33

Фяшя
Участник
Зарегистрирован: 22.02.2011
Сообщений: 11

Re: Очень сложный запрос SELECT для выбора Рейтинга

Евгений! Спасибо огромное! Но данная конструкция (@pos:=@pos+1) выводит Рейтинговые позиции только для
alles (all_pos)

а надо еще week_pos , month_pos...

покажите пожалуйста пример с хотя бы двумя pos например (all_pos,exclude_today_pos )

Неактивен

 

#8 22.11.2011 23:06:54

evgeny
Гуру
Зарегистрирован: 04.05.2009
Сообщений: 335

Re: Очень сложный запрос SELECT для выбора Рейтинга


SELECT
`all`.uid AS uid,
`all`.cnt AS alles,  
`all`.pos AS all_pos,  
`exclude_today`.cnt AS exclude_today,
`exclude_today`.ed_pos AS ed_pos,    
`last_week`.cnt  AS last_week,
`last_week`.lw_pos  AS lw_pos      
FROM (
SELECT a.*,(@pos:=@pos+1) pos  FROM
    (SELECT uid,COUNT(uid) cnt FROM championat_history WHERE `status`=1 GROUP BY uid ORDER BY cnt DESC) a,(select @pos:=0) z
) `all`
LEFT JOIN
  (SELECT a.*,(@ed_pos:=@ed_pos+1) ed_pos  FROM
    (SELECT COUNT(uid) cnt,uid FROM championat_history WHERE `status`=1
   AND DATE(`time`)!=CURDATE() GROUP BY uid ORDER BY cnt DESC) a,(select @ed_pos:=0) z
) `exclude_today` ON(all.uid=`exclude_today`.uid)
LEFT JOIN
  (SELECT a.*,(@lw_pos:=@lw_pos+1) lw_pos  FROM
    (SELECT COUNT(uid) cnt,uid FROM championat_history WHERE `status`=1
   AND (`time`)>NOW()-INTERVAL 1 WEEK GROUP BY uid ORDER BY cnt DESC) a,(select @lw_pos:=0) z
) `last_week` ON(all.uid=`last_week`.uid)



Вот условие, для этой недели
YEAR(`time`)=YEAR(NOW()) AND WEEK(`time`)=WEEK(NOW())
для прошлой недели
YEAR(`time`)=YEAR(NOW()-INTERVAL 1 WEEK) AND WEEK(`time`)=WEEK(NOW()-INTERVAL 1 WEEK)

Остальное потому же принципу.

Отредактированно evgeny (22.11.2011 23:36:35)

Неактивен

 

#9 23.11.2011 10:59:27

Фяшя
Участник
Зарегистрирован: 22.02.2011
Сообщений: 11

Re: Очень сложный запрос SELECT для выбора Рейтинга

Evgeny, Спасибо милый человек! Очень ценю ваш труд и время потраченное вами на помощь мне.
Дай вам бог здоровья и благополучия!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson