Нестабильный запрос

camka

не самка
Нестабильный запрос

Собственно запрос:

select case image.title when '' then image.filename else image.title end as title,
image.id as image_id,
user.login,
user.id as user_id,
max(image.createdate),
DATE_FORMAT(max(image.createdate),'%d-%m-%Y')as createdate
from image
inner join album
on album.id=image.album_id
inner join user
on user.id=album.user_id
where album.private=0
group by user.id
order by 5
desc limit 12

Служит для выбора по одной последней закачанной картинке для каждого пользователя, вернее 12-ти последних закачаных картинок.

Проблема: Дата последней картинки выбирается правильно, однако ID картинки не обязательно является именно той картинкой, дата которой отображается, а может быть ID любой другой (закономерность не выявлена) картинки того же пользователя и не обязательно из того же альбома.

Вопрос: Собственно почему вообще отрабатывает подобный запрос и не выдает ошибки еще при парсинге, ведь отсутствует группировка по полю image.id да и вообще какой-либо связи между максимальной датой и id картинки нету?

Решение: на данный момент решил задачу слегка кривым, но для меня работающим способом, заменив в выбираемых полях поле image.id на max(image.id), поскольку у последней картинки всегда наибольший id.
 

Demiurg

Guest
Опиши, пожалуйста, структуру твоих табличек.
 

tony2001

TeaM PHPClub
Вопрос: Собственно почему вообще отрабатывает подобный запрос и не выдает ошибки еще при парсинге, ведь отсутствует группировка по полю image.id да и вообще какой-либо связи между максимальной датой и id картинки нету?
это один из недостатков MySQL.
 

Falc

Новичок
tony2001
>>это один из недостатков MySQL.

Иногда такие недостатки бывают крайне полезны :)
 

camka

не самка
А структура незамысловатая.

Если сократить до минимума то:

IMAGE
--------
id
title
filename
album_id
createdate
--------------


ALBUM
--------
id
private
user_id
----------


USER
--------
id
login
--------

-~{}~ 09.02.04 11:54:

То есть вы хотите сказать, что поведение MySQL в таких случаях непредсказуемо? Есть ли может где-то в мануале почитать про эдакую нестабильность?

-~{}~ 09.02.04 11:56:

может тогда в таком случае в grop by стоить и user.login пихнуть, а то начнет шалить, не остановишь.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: camka
То есть вы хотите сказать, что поведение MySQL в таких случаях непредсказуемо?
По стандарту SQL запрос вообще некорректен. MySQL как обычно умнее стандарта, сам его выбрал --- теперь не жалуйся.
 

Falc

Новичок
Sad Spirit
>>По стандарту SQL запрос вообще некорректен. MySQL как обычно умнее стандарта, сам его выбрал --- теперь не жалуйся.

невижу ничего плохого в том что некорректный запрос неккоректно работает :)
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: Falc
невижу ничего плохого в том что некорректный запрос неккоректно работает :)
Это, конечно, вопрос философский.
Плохое в том, что ты рискуешь узнать об ошибке по факту обнаружения в базе неверных данных.
Программа не должна пытаться быть умнее тебя и "догадываться", что на самом деле ты имел в виду. Если команда неоднозначна -> ошибка.
 

tony2001

TeaM PHPClub
да никто ни о чем не догадываться и не пытается быть умней, чем остальные.
это фича парсера муськи, насколько я понимаю.
о причинах её существования -> mysql.com
 

Falc

Новичок
Sad Spirit
вот смотри пример, когда дополнительные группировки только заторомзят выборку:

select table1.id, table1.name, table1.val1, table1.val2 ....
.....
GROUP BY table1.id

В мускуле не нужно групировать, по всем полям, этот запрос корректен с точки зрния логики, но по стандарту нужно групировать по всем полям :(
 

camka

не самка
вот смотри пример, когда дополнительные группировки только заторомзят выборку:

select table1.id, table1.name, table1.val1, table1.val2 ....
.....
GROUP BY table1.id

В мускуле не нужно групировать, по всем полям, этот запрос корректен с точки зрния логики, но по стандарту нужно групировать по всем полям
Вот я и спрашиваю, насколько верно то, что mysql выдаст тебе достоверные данные по полям table1.name, table1.val1, table1.val2, потому как вот у меня как раз данные были не те. Или в моем варианте виноват джойн?
 

Falc

Новичок
camka
Я под "table1.id" понимал первичный ключ, так что в даном случае достоверность данных гарантирована.

Чесно сказать с твоим запросом я не разбирался. но навскидку могу сказать что гамотные люди так не пишут: "order by 5 "

-~{}~ 09.02.04 14:16:

camka
Посмотрел твой запрос, интересно какой image.id ты хочешь получить если групируешь по user.id ?
 

camka

не самка
Посмотрел твой запрос, интересно какой image.id ты хочешь получить если групируешь по user.id ?
Тот image.id, который соответствует той же строке в таблице image, что и запись с максимальной датой.
 

Falc

Новичок
camka
А если у тебя еще будет:
max(image.createdate), min(image.createdate)

В мускуле пока нет телепатического модуля и определить какие имено нужны тебе записи, если сама ему об этом не скажешь, он не может :)
 

camka

не самка
Вот я и думал, в чем причина того, что запрос вообще отрабатывает. Теперь вроде ясно.

Цитата из мануала:

Don't use this feature if the columns you omit from the GROUP BY part aren't unique in the group! You will get unpredictable results.

Спасибо всем за объяснения.
 

Sad Spirit

мизантроп (Старожил PHPClub)
Команда форума
Автор оригинала: Falc
Sad Spirit
вот смотри пример, когда дополнительные группировки только заторомзят выборку:

select table1.id, table1.name, table1.val1, table1.val2 ....
.....
GROUP BY table1.id
Как правило такие запросы можно переписать с использованием подзапросов, тогда группировка не понадобится. ;)
 

Falc

Новичок
Sad Spirit
>>можно переписать с использованием подзапросов

Ну вот опять удар ниже пояса :(
 

chira

Новичок
если нужно:
вернее 12-ти последних закачаных картинок.
по моему такой SQL логичнее:
Код:
SELECT case image.title when '' then image.filename else image.title end as title, 
image.id as image_id, 
user.login, 
user.id as user_id, 
image.createdate, 
DATE_FORMAT(image.createdate,'%d-%m-%Y')as createdate 
FROM image,album,user 
WHERE album.id=image.album_id
 AND user.id=album.user_id
 AND album.private=0 
order by 5 desc
limit 12
без GROUP BY и получаем последние 12 картинок ...
юзеры , уже как попадутся ...
 

chira

Новичок
тогда через временную таблицу
если тебя устроит такое усливие:- самая новая картинка будет иметь больший id, то:
Код:
CREATE TEMPORARY TABLE tt
AS SELECT a.user_id, MAX(i.id) id
FROM image i,album a
WHERE a.id=i.album_id
  AND a.private=0 
GROUP BY a.user_id
ORDER BY id desc
LIMIT 12

SELECT case i.title when '' then i.filename else i.title end as title, 
i.id as image_id, 
u.login, 
u.id as user_id, 
i.createdate, 
DATE_FORMAT(i.createdate,'%d-%m-%Y')as createdate 
FROM image i,tt,user u
WHERE tt.id=i.id
 AND u.id=tt.user_id
order by 5 desc
 
Сверху