SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 12.03.2014 12:34:01

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Distinct, group by или еще какой вариант?

Добрый день.

Есть таблица вида:

id user_id name status
1  1   Ivan 1
2  2   Petr 1
3  3   Vasya 1
4  1 Ivan 100
5  4 Sasha 100

Как получить такой результат:
2  2   Petr 1
3  3   Vasya 1
4  1 Ivan 100
5  4 Sasha 100

Т.е. если у user_id есть строка со статусом 100 - оставить ее, и не выводить строку, где у него статус 1.

Дистинкт не работает, group by оставляет строку со статусом 1. Явно как-то должно это просто работать. smile
Заранее спасибо.

Неактивен

 

#2 12.03.2014 14:46:43

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

group все-таки работает, я не по тому полю группировал. smile

Неактивен

 

#3 26.03.2014 15:52:32

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

В результате получаю вот такой запрос:

           SELECT * FROM
            (SELECT * FROM
            (SELECT
            m.id,
            tournament_id,
            (CASE tournament_id
                   WHEN 257 THEN 'MHA'
                   WHEN 258 THEN 'MHB'
                   WHEN 260 THEN 'M1A'
                   WHEN 261 THEN 'M1B'
                   WHEN 265 THEN 'M2A'
                   WHEN 266 THEN 'M2B'
                   WHEN 268 THEN 'M3A'
                   WHEN 269 THEN 'M3B'
                   WHEN 270 THEN 'M3C'
                   WHEN 271 THEN 'M3D'
                   WHEN 273 THEN 'M4A'
                   WHEN 274 THEN 'M4B'
                   WHEN 275 THEN 'M4C'
                   WHEN 276 THEN 'M4D'
                   WHEN 277 THEN 'WH'
                   WHEN 279 THEN 'W1A'
                   WHEN 280 THEN 'W1B'
                   WHEN 283 THEN 'W2A'
                   WHEN 284 THEN 'W2B'
                ELSE 'n/a'
            END) as gruppa,
            t1.name as Team1Name,
                        t1.contact_id as Team1ContactId,
            t2.name as Team2Name,
                        t2.contact_id as Team2ContactId,
            m.dt,
            DATE_FORMAT(m.dt, '%Y-%M-%d') AS formatted_date,
            mr.dt_accept,
            mr.status,
            mr.team1_set1_point,
            mr.team2_set1_point,
            mr.team1_set2_point,
            mr.team2_set2_point,
            mr.team1_set3_point,
            mr.team2_set3_point,
            mr.team1_set4_point,
            mr.team2_set4_point,
            mr.team1_set5_point,
            mr.team2_set5_point,
                        mr.arbiter1_id,
                        mr.arbiter2_id,
                        mr.arbiter1_mark,
            mr.author_id,
            mr.comment,
            mr.moder_comment
            FROM `match` m
            JOIN match_raw AS mr ON match_id = m.id
            JOIN team AS t1 ON m.team1 = t1.id
            JOIN team AS t2 ON m.team2 = t2.id
            WHERE mr.dt_accept > NOW() - INTERVAL 5 DAY
            ORDER BY  `m`.`id` ,  `m`.`dt` DESC , `mr`.`status` DESC) as res
            GROUP BY id) as rawresults
            UNION
            SELECT
            m.id,
            tournament_id,
            (CASE tournament_id
                   WHEN 257 THEN 'MHA'
                   WHEN 258 THEN 'MHB'
                   WHEN 260 THEN 'M1A'
                   WHEN 261 THEN 'M1B'
                   WHEN 265 THEN 'M2A'
                   WHEN 266 THEN 'M2B'
                   WHEN 268 THEN 'M3A'
                   WHEN 269 THEN 'M3B'
                   WHEN 270 THEN 'M3C'
                   WHEN 271 THEN 'M3D'
                   WHEN 273 THEN 'M4A'
                   WHEN 274 THEN 'M4B'
                   WHEN 275 THEN 'M4C'
                   WHEN 276 THEN 'M4D'
                   WHEN 277 THEN 'WH'
                   WHEN 279 THEN 'W1A'
                   WHEN 280 THEN 'W1B'
                   WHEN 283 THEN 'W2A'
                   WHEN 284 THEN 'W2B'
                ELSE 'n/a'
            END) as gruppa,
            t1.name as Team1Name,
                        t1.contact_id as Team1ContactId,
            t2.name as Team2Name,
                        t2.contact_id as Team2ContactId,
            m.dt,
           DATE_FORMAT(m.dt, '%Y-%M-%d') AS formatted_date,
            NULL AS dt_accept,
            0 AS status,
            '' AS team1_set1_point,
            '' AS team2_set1_point,
            '' AS team1_set2_point,
            '' AS team2_set2_point,
            '' AS team1_set3_point,
            '' AS team2_set3_point,
            '' AS team1_set4_point,
            '' AS team2_set4_point,
            '' AS team1_set5_point,
            '' AS team2_set5_point,
            '' AS arbiter1_id,
            '' AS arbiter2_id,
            '' AS arbiter1_mark,
            '' AS author_id,
            '' AS comment,
            '' AS moder_comment
            FROM `match` m
            JOIN team AS t1 ON m.team1 = t1.id
            JOIN team AS t2 ON m.team2 = t2.id
            WHERE dt < NOW() and HAVE_RESULT = 0 AND m.id not in (SELECT mr.match_id FROM match_raw mr)
ORDER BY formatted_date DESC, tournament_id


А нет идей, как уйти от вложенных запросов?

Неактивен

 

#4 26.03.2014 16:15:04

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

А еще вдогонку пришло письмо от хостера, что этот запрос создает повышенную нагрузку на сервер.

Отображает строки 0 - 29 ( 82 всего, Запрос занял 0.0134 сек.)

Я вот думаю, одна сотая на выполнение запроса - это реально повышенная нагрузка? При том, что на страницу, где идет этот запрос заходят максимум 5-10 человек в час.

Неактивен

 

#5 26.03.2014 16:51:24

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

Re: Distinct, group by или еще какой вариант?

В вашем запросе без поллитры на обойтисьsmile
Если возвращаться к постановке вопроса из первого поста, то посмотрите статью http://sqlinfo.ru/articles/info/18.html
Вам подойдет первый способ с небольшими изменениями, если я правильно понял задачу.


Время, которое вы показываете - это время выполнения самого запроса или отдачи его из кеша?

Неактивен

 

#6 26.03.2014 17:06:46

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

Время, которое показываю - это то, что мне myadmin показывает. Из кеша это или сам запрос - не знаю как определить.

Но я тут поковырялся с explain и выяснил, что у меня там

3
DERIVED
mr
ALL
i_match_id
NULL
NULL
NULL
264
100.00
Using where; Using temporary; Using filesort

4
UNION
m
ALL
i_team1,i_team2
NULL
NULL
NULL
5849
100.0

Т.е. получается, что используются 264*5849 строк (1,5 млн!). 264 из верхней части запрос, а 5849 дает юнион (вторая часть).

Вопрос - почему оно дает 5849 строк, если там условие where стоит четкое абсолютно? (там реально не больше 100 строк выходит в результате)

Отредактированно Bust_Ed (26.03.2014 17:07:09)

Неактивен

 

#7 26.03.2014 17:23:26

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

Re: Distinct, group by или еще какой вариант?

Bust_Ed написал:

Время, которое показываю - это то, что мне myadmin показывает. Из кеша это или сам запрос - не знаю как определить.

select sql_no_cache ....

Bust_Ed написал:

Но я тут поковырялся с explain и выяснил, что у меня там

3
DERIVED
mr
ALL
i_match_id
NULL
NULL
NULL
264
100.00
Using where; Using temporary; Using filesort

4
UNION
m
ALL
i_team1,i_team2
NULL
NULL
NULL
5849
100.0

Т.е. получается, что используются 264*5849 строк (1,5 млн!). 264 из верхней части запрос, а 5849 дает юнион (вторая часть).

Вопрос - почему оно дает 5849 строк, если там условие where стоит четкое абсолютно? (там реально не больше 100 строк выходит в результате)

union это сложение, а не перемножение.

5849 - число строк, которые MySQL ожидает перебрать для выполнения данного запроса.

P.S. Почему вы не хотите переписать запрос в соответствии с рекомендацией из статьи? Он будет гораздо проще.

Неактивен

 

#8 26.03.2014 17:28:13

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

Статью сижу читаю, пожалуй, вы правы.

Переделаю завтра, на свежую голову.

Спасибо.

Неактивен

 

#9 11.04.2014 13:39:22

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

Так, вроде заработало.

При ближайшем рассмотрении, не работает. В статье используется довольно простая группировка. Вот она у меня как-то не так работает.


SELECT  `id` ,  `match_id` ,  `dt_accept`
FROM match_raw
WHERE match_id =6341
LIMIT 0 , 30
 


Дает такой результат:

id    match_id    dt_accept
12866    6341    10.04.2014 13:27
12867    6341    10.04.2014 13:38
12868    6341    10.04.2014 13:46
12869    6341    10.04.2014 14:08
12870    6341    10.04.2014 14:08
12871    6341    10.04.2014 14:08
12872    6341    10.04.2014 14:09
12873    6341    10.04.2014 14:55
12874    6341    10.04.2014 15:08
12875    6341    10.04.2014 15:17

Теперь добавляю группировку. Т.е. хочу получить матч_айди у которого самая свежая дата внесения (по сути, это 12875, но можеть быть случай, когда у 12875, например, дата будет более старая, чем у 12873, т.к. 12873 можно отредактировать и дата обновится).


SELECT  `id` ,  `match_id` , MAX(  `dt_accept` ) AS  `latest_date` ,  `dt_accept`
FROM match_raw
WHERE match_id =6341
GROUP BY  `match_id`
LIMIT 0 , 30
 


Получаю вот это:

id    match_id    latest_date           dt_accept
12866    6341    10.04.2014 15:17      10.04.2014 13:27

Как так? smile Он мне выдает latest_date правильно, но при этом результат матча не того, от которого latest_date посчитался.

Отредактированно Bust_Ed (11.04.2014 13:40:38)

Неактивен

 

#10 11.04.2014 15:31:04

Bust_Ed
Завсегдатай
Откуда: Москва
Зарегистрирован: 13.11.2013
Сообщений: 48

Re: Distinct, group by или еще какой вариант?

В общем, я ниче не хочу сказать, но группировка как написано в статье на сайте - не работает.

Вот так работает группировка:

SELECT mr1.*
FROM `match_raw` AS mr1
LEFT OUTER JOIN `match_raw` AS mr2
  ON mr1.match_id = mr2.match_id AND mr1.dt_accept < mr2.dt_accept
WHERE mr2.match_id IS NULL

Неактивен

 

Board footer

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