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

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

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

Вы не зашли.

#1 14.02.2012 16:22:34

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Сортировка работает, не так как хочу, помогите исправить

Таблица:


CREATE TABLE IF NOT EXISTS `0` (
  `fid` int(10) unsigned NOT NULL,
  `tid` int(10) unsigned NOT NULL,
  `mid` bigint(20) unsigned NOT NULL,
  `from` varchar(255) collate utf8_unicode_ci NOT NULL,
  `text` longtext collate utf8_unicode_ci NOT NULL,
  `readed` tinyint(1) unsigned NOT NULL,
  `time` int(10) unsigned NOT NULL,
  UNIQUE KEY `mid` (`mid`),
  KEY `fid` (`fid`),
  KEY `tid` (`tid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `0` (`fid`, `tid`, `mid`, `from`, `text`, `readed`, `time`) VALUES
(1, 2, 354345, '', 'dfgdsgf', 0, 435345),
(1, 2, 121329075128, '', 'xxx', 0, 1329075128),
(2, 1, 121329138885, 'A', 'dadada', 0, 1234567890),
(1, 2, 121329213183, 'B', 'netnetnet', 0, 1234567895),
(3, 1, 456564364356, 'C', 'gbgbgb', 0, 1234567898),
(1, 3, 4326435635465, 'A', 'brbrbr', 0, 1234567896);
 


Запрос:

SELECT *
FROM `0`
WHERE fid =1
OR tid =1
GROUP BY fid, tid
ORDER BY time DESC
 

Цель получить последние послание из чата двух юзеров, все сообщения не нужны. Объединила по fid,tid, выходит две строки, но это не страшно в PHP отсеяла лишнее, проблема в сортировки, не знаю, почему, но запрос походу сначала берёт ПЕРВОЕ значение каждой группы, а потом сортирует результат по времени уже выдернутого, а надо наоборот, чтоб выдёргивал последние, сортируя по группам.

Отредактированно animegirl (14.02.2012 16:44:17)


Скажи миру - НЯ!

Неактивен

 

#2 14.02.2012 19:10:23

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сортировка работает, не так как хочу, помогите исправить

Это иллюстрация того почему при группировке нельзя выбирать поля без группирующих функций.


Для простоты рассмотрим след пример
SELECT * FROM `0` WHERE fid =1 GROUP BY fid;
У вас в таблице есть 4 строки, удовлетворяющих условию fid =1. При группировке мы оставляем одну строку. Вопрос какую строку выберет сервер? Ответ - любую.
Стандарт SQL запрещает такие запросы, однако сервер MySQL их позволяет и даже не ругается, отчего новички и совершают подобные промахи.

Возвращаясь к вашему вопросу - сортировка происходить после группировки, т.е. после того как выбрана случайная строка для каждой пары значений fid, tid.
От того, кстати, и происходит удвоение результатов, так как 1,2 и 2,1 - разные пары значений fid, tid.

Неактивен

 

#3 14.02.2012 20:16:50

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Сортировка работает, не так как хочу, помогите исправить

Ну удвоение результатов не страшно, а как задачу решить?


Скажи миру - НЯ!

Неактивен

 

#4 14.02.2012 20:43:43

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сортировка работает, не так как хочу, помогите исправить

animegirl написал:

Ну удвоение результатов не страшно,

yikesyikesyikes А утроение ?

select * from
(select fid, tid, max(`time`) mtime from
(SELECT fid, tid, `time` FROM `0` WHERE fid =1
union
SELECT tid, fid, `time` FROM `0` WHERE tid =1) t group by tid) t1
join `0`on ((t1.fid=`0`.fid and t1.tid=`0`.tid) or (t1.fid=`0`.tid and t1.tid=`0`.fid)) and t1.mtime=`0`.`time`;

Только вместо * в первой строке перечислите нужные вам поля.

Неактивен

 

#5 15.02.2012 01:30:27

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Сортировка работает, не так как хочу, помогите исправить

Нашла тут такой вариант:

SELECT usr, SUBSTR(MAX(CONCAT(dt, post)), 1, 19) dt, SUBSTR(MAX(CONCAT(dt, post)), 20) post
FROM posts
GROUP BY usr

Не могу только понять схему его работы (


Скажи миру - НЯ!

Неактивен

 

#6 15.02.2012 01:53:16

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сортировка работает, не так как хочу, помогите исправить

Логика проста - при использовании группировки в части перечисления полей (после ключевого слова select) могут быть только те колонки по которым производится группировка или они используются с группирующей ф-ей (min,sum,count и т.д.)

В данном примере, на сколько я понимаю, вы хотите выбрать для каждого юзера последнее сообщение. По usr проводится группировка, дата последнего сообщения это max(dt), а колонка post без группирующей ф-ии, т.е. будет выбрана произвольная. Чтобы это обойти, время и сообщение объединяют в одну строку CONCAT(dt, post), от которой берут максимум.
А потом снова разделяют. 19 символов это формат даты ('2012-02-15 01:47:19').

Неактивен

 

#7 15.02.2012 02:32:47

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Сортировка работает, не так как хочу, помогите исправить

Я правильно понимаю, что тут решена моя задача в один запрос? Как его только на мою таблицу перенести не совсем допонимаю ((


Скажи миру - НЯ!

Неактивен

 

#8 15.02.2012 02:37:37

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Сортировка работает, не так как хочу, помогите исправить

Нет, не правильно.
Чем вас не устраивает решение из поста №4?

Неактивен

 

#9 15.02.2012 02:41:34

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Сортировка работает, не так как хочу, помогите исправить

4 селекта, к тому же унион и джойн, для операции которая будет происходит очень часто, это выйдет убийством DB сервера


Скажи миру - НЯ!

Неактивен

 

#10 19.02.2012 20:04:46

animegirl
Активист
Зарегистрирован: 28.07.2011
Сообщений: 288

Re: Сортировка работает, не так как хочу, помогите исправить

Решила свою задачу таким способом:

SELECT *
FROM (SELECT * FROM `0` WHERE fid=1 OR tid=1 ORDER BY time DESC) AS tabl
GROUP BY fid,tid


Скажи миру - НЯ!

Неактивен

 

Board footer

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