Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Заблудился с GROUP By. Запрос из 3 таблиц
 
 автор: ddhvvn   (17.05.2010 в 11:39)   письмо автору
 
 

Приветствую.
Есть3 таблицы
CREATE TABLE `users` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `login` varchar(50) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

CREATE TABLE `nominations` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `title` varchar(250) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

CREATE TABLE `works` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `user` mediumint(8) unsigned NOT NULL,
  `nomination` mediumint(8) unsigned NOT NULL,
  `current_rating` float(4,2) unsigned NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;


Примерчик дампа

INSERT INTO `users` (`id`, `login`) VALUES(1, 'user1');
INSERT INTO `users` (`id`, `login`) VALUES(2, 'user2';
INSERT INTO `users` (`id`, `login`) VALUES(3, 'user3');

INSERT INTO `nominations` (`id`, `title`) VALUES(1, 'Номинация 1');
INSERT INTO `nominations` (`id`, `title`) VALUES(2, 'Номинация 2');

INSERT INTO `works` (`id`, `user`, `nomination`,`current_rating`) VALUES(1, 1, 1, 4.50);
INSERT INTO `works` (`id`, `user`, `nomination`,`current_rating`) VALUES(2, 2, 1, 4.56);
INSERT INTO `works` (`id`, `user`, `nomination`,`current_rating`) VALUES(3, 1, 2, 6.00);
INSERT INTO `works` (`id`, `user`, `nomination`,`current_rating`) VALUES(4, 2, 2, 6.25);
INSERT INTO `works` (`id`, `user`, `nomination`,`current_rating`) VALUES(5, 3, 2, 7.90);


Мне нужно выбрать лидеров номинации. Так как голосуется не за человека, за работу, то, соответственно, сделать это нужно косвенно через таблицу works )

Что делаю
SELECT t1.title, MAX(t2.current_rating) AS current_rating, t3.*
FROM `nominations` AS t1, works AS t2, users AS t3
WHERE t2.nomination=t1.id AND t2.user=t3.id
GROUP BY t1.id;


Получаю
Номинация1      4.56      1      user1
Номинация2     7.90     1     user1

Туплю и не пойму какого фига, у меня пользователи склеиваются "в одного"?

  Ответить  
 
 автор: root   (17.05.2010 в 12:17)   письмо автору
 
   для: ddhvvn   (17.05.2010 в 11:39)
 

А Вы чего ожидали? У Вас атрибуты таблицы users не являются параметрами агрегатных функций и не используются в условии GROUP BY.
Из чего следует, что в списке SELECT им вообще делать нечего.
MySQL, к сожалению, позволяет выполнять такого рода запросы, и в Вашем случае выбирает первого попавшегося при операции GROUP BY пользователя (другие СУРБД сразу выдают ошибку, т.к. нет гарантии, что условие вернёт один единственный результат для группы).

  Ответить  
 
 автор: ddhvvn   (17.05.2010 в 13:45)   письмо автору
 
   для: root   (17.05.2010 в 12:17)
 

А более "по-русски" можно? ) или хотя бы что и как изменить? или пример?

  Ответить  
 
 автор: root   (17.05.2010 в 14:49)   письмо автору
 
   для: ddhvvn   (17.05.2010 в 13:45)
 

Скорее всего нужно будет соединить таблицу works с самой собой. Во всяком случае это первое, что мне в голову пришло :-)

SELECT n.title, w.current_rating, u.id, u.login
FROM works w
INNER JOIN
(
  SELECT MAX(current_rating) cr, nomination
    FROM works
  GROUP BY  nomination
) AS wk ON wk.nomination = w.nomination AND wk.cr = w.current_rating
LEFT JOIN users u ON w.user = u.id
LEFT JOIN nominations n ON w.nomination = n.id

  Ответить  
 
 автор: ddhvvn   (17.05.2010 в 15:13)   письмо автору
 
   для: root   (17.05.2010 в 14:49)
 

хмм.. вроде работает, спасибо!
только учитывая, что из этих 3 таблиц самая большая - works и что выборка по works происходит дважды, не слишком затратно это выйдет в будущем? )

id     select_type     table     type     possible_keys     key     key_len     ref     rows     Extra
1     PRIMARY     <derived2>     ALL     NULL     NULL     NULL     NULL     2      
1     PRIMARY     w     ALL     NULL     NULL     NULL     NULL     5     Using where
1     PRIMARY     u     eq_ref     PRIMARY     PRIMARY     3     db.w.user    1      
1     PRIMARY     n     eq_ref     PRIMARY     PRIMARY     3     wk.nomination     1      
2     DERIVED     works     ALL     NULL     NULL     NULL     NULL     5     Using temporary; Using filesort

  Ответить  
 
 автор: root   (17.05.2010 в 16:16)   письмо автору
 
   для: ddhvvn   (17.05.2010 в 15:13)
 

>хмм.. вроде работает, спасибо!
>только учитывая, что из этих 3 таблиц самая большая - works и что выборка по works происходит дважды, не слишком затратно это выйдет в будущем? )

я вряд ли смогу Вам дать однозначный ответ.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования