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

Форум MySQL

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

 

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

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

тема: вывод из базы с максимальным значением поля
 
 автор: Slo_Nik   (16.12.2009 в 12:57)   письмо автору
 
 

Добрый день.
Помогите, пожалуйста, довести до ума запрос.
есть две таблицы, первая это группы фотографий(всего 3), вторая это фотографии для определённой группы. вторая таблица привязана к первой по id записи в первой таблице.
во второй таблице есть поле "quote" куда заносятся результаты голосования для фото, по умолчанию значение поля равно 0, при каждом голосовании значение увеличивается на 1.
надо вывести на страницу три записи так, что бы для каждой группы выводилось одно фото, с максимальным значением поля quote.
попробовал сделать запрос к двум таблицам сразу, записи выводятся, но не так как надо.

SELECT `contest_cat`.`name` AS `name`,
                  `contest_cat`.`id_contest_cat` AS `id_contest_cat`,
                  `contest`.`id_contest` AS `id_us`,
                  `contest`.`titleph` AS `title`,
                  `contest`.`small` AS `small`,
                  `contest`.`big` AS `big`,
              MAX(`contest`.`quote`) AS `quote`
             FROM `contest_cat`,`contest`
            WHERE `contest`.`id_contest_cat` = `contest_cat`.`id_contest_cat`
              AND `contest`.`hide` = 'show'
              AND `contest_cat`.`hide` = 'show'
            GROUP BY `quote`
            ORDER BY `quote` LIMIT 3

contes_cat таблица с группами, contest это таблица с фотографиями для определённой группы.
при таком запросе выводится фото только для двух групп и не с максимальным значением поля quote, для третьей группы вообще ни чего не выводится.
короче, запутался окончательно, подскажите, как правильно сделать?

  Ответить  
 
 автор: Лена   (16.12.2009 в 13:17)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 12:57)
 

У вас должно быть соединение таблиц через LEFT JOIN. А второй таблицы contest в запросе нет.

  Ответить  
 
 автор: Slo_Nik   (16.12.2009 в 13:22)   письмо автору
 
   для: Лена   (16.12.2009 в 13:17)
 

не понял, как нет второй таблицы?

  Ответить  
 
 автор: Trianon   (16.12.2009 в 13:30)   письмо автору
 
   для: Лена   (16.12.2009 в 13:17)
 

Есть, да только как обычно, через запятую...

  Ответить  
 
 автор: Slo_Nik   (16.12.2009 в 13:38)   письмо автору
 
   для: Trianon   (16.12.2009 в 13:30)
 

в таком случае как запятая влияет на запрос?

  Ответить  
 
 автор: Trianon   (16.12.2009 в 13:45)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 13:38)
 

Не дает создать внешне левостороннее соединение.
Вынуждает делать его внутренним. Что, по Вашему описанию, проблему не решает.
(Ну это помимо идеи о деревянных пулях)

  Ответить  
 
 автор: Trianon   (16.12.2009 в 14:10)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 13:38)
 

Забыл сказать, это не основная проблема.
Главное - Ваш запрос неоднозначен по GROUP BY - он в разделе SELECT перечисляет негруппирующие поля за рамками агрегатных функций. Так писать нельзя (хоть сервер MySQL и позволяет), поскольку никакого разумного результата такой запрос не вернет.

Очень грубый пример:
SELECT a, MAX(b), с, d 
  FROM tbl
  GROUP BY a, d;

В списке SELECT 4 поля : a, b, c и d.
Поле a и d писать можно, поскольку они группирующие ( перечислены в GROUP BY),
поле b писать можно, поскольку оно является параметром агрегатной функции MAX(),
поле с писать нельзя, поскольку его нет ни там, ни там. Его значение неоднозначно.

  Ответить  
 
 автор: Slo_Nik   (16.12.2009 в 15:19)   письмо автору
 
   для: Trianon   (16.12.2009 в 14:10)
 

тогда как быть, если помимо группирирующих параметров мне надо получить ещё и те которые за рамками агрегатных функций?
т.е. мне надо вывести "имя группы"(всего 3) +id группы и для каждой группы одно фото, где quote максимально + пути к фото + id фото ?
у меня сейчас получается вывод
1-я группа + 1-но фото с max quote, quote не принадлежит этому фото
2-я группа + 1-но фото с max quote, quote не принадлежит этому фото
2-я группа + 1-но фото с max quote, quote не принадлежит этому фото
а надо
1-я группа + 1-но фото с max quote
2-я группа + 1-но фото с max quote
3-я группа + 1-но фото с max quote

  Ответить  
 
 автор: Trianon   (16.12.2009 в 15:41)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 15:19)
 

а группирование по какому полю требуется?
От него и отталкиваться.
Остальные поля подключать соединением с таблицей.
вот здесь я описал

  Ответить  
 
 автор: Slo_Nik   (16.12.2009 в 16:44)   письмо автору
 
   для: Trianon   (16.12.2009 в 15:41)
 

как я понимаю, группировать надо не по одному полю.
вывести группы, к каждой привязать одно фото из группы с максимальным quote
вот здесь я и запутался, не могу ни как в голове сложить как лучше группировать...

  Ответить  
 
 автор: Trianon   (16.12.2009 в 16:48)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 16:44)
 

В принципе, бывают случаи, когда требуется группировать запрос по нескольким полям.
Но у Вас-то фактор группировки один?

  Ответить  
 
 автор: Slo_Nik   (16.12.2009 в 18:03)   письмо автору
 
   для: Trianon   (16.12.2009 в 16:48)
 

группировать да, по полю quote, надо получить с максимальным значением.
а сортировка, если фото с одинаковым значением quote две и более, то сортировать по id .
если я заблуждаюсь по поводу группировки, то поправьте меня.

  Ответить  
 
 автор: Trianon   (16.12.2009 в 23:10)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 18:03)
 

Приведите структуру таблиц (а то непонятно даже в какой таблице у Вас quote и какого типа. )
SHOW CREATE TABLE contest;
и т.п.
И напишите простой запрос, в котором Вы вытаскиваете сгруппированное quote и значения агрегатных функций. И всё.
Следующий шаг - потом.
Всякие остальные поля, любые сортировки - всё позднее.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 01:31)   письмо автору
 
   для: Trianon   (16.12.2009 в 23:10)
 

таблица с фотографиями(здесь находится quote)
+----------------+---------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------------------+----------------+
| id_contest | int(8) | NO | PRI | NULL | auto_increment |
| author | tinytext | NO | | |
|
| email | tinytext | YES | | NULL |
|
| titleph | tinytext | YES | | NULL |
|
| small | tinytext | NO | | |
|
| big | tinytext | NO | | |
|
| hide | enum('show','hide') | NO | | hide |
|
| quote | int(10) | NO | | 0 |
|
| date | datetime | YES | | 0000-00-00 00:00:00 |
|
| id_contest_cat | int(11) | NO | | 0 |
|
+----------------+---------------------+------+-----+---------------------+----------------+
таблица групп фотографий
+----------------+---------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------------------+----------------+
| id_contest_cat | int(8) | NO | PRI | NULL | auto_increment |
| name | tinytext | NO | | |
|
| description | text | NO | | |
|
| hide | enum('show','hide') | NO | | hide |
|
| data | datetime | NO | | 0000-00-00 00:00:00 | |
+----------------+---------------------+------+-----+---------------------+----------------+

SELECT `id_contest`, MAX(`quote`) AS mquote FROM `contest` GROUP BY `quote` LIMIT 3

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

3 группа
d_contest = 56
mquote = 2
1 группа
id_contest = 62
mquote = 9
1 группа
id_contest = 64
mquote = 10

  Ответить  
 
 автор: Trianon   (17.12.2009 в 01:38)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 01:31)
 

Вам так трудно было выполнить запросы
SHOW CREATE TABLE contest;
SHOW CREATE TABLE contest_cat;
и привести результаты здесь?
Зачем этот изврат?

Или Вы полагаете что по этим, с позволения сказать, чертежам восстановить таблицы проще?



И таки Вы уверены, что группирование ведется по quote, а не по id_contest_cat?

Потому что SELECT MAX(aaa) FROM tbl GROUP BY aaa - это чушь.
Понимаете, нет смысла спрашивать какой максимум в колонке aaa, разделив весь набор на группы с равными значениями aaa .
Если значения в группе все равны, то и максимум будет равен значению, и минимум, и вообще любой элемент.

Похоже, помимо структуры, придется привести еще и фрагмент дампа данных.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 01:55)   письмо автору
 
   для: Trianon   (17.12.2009 в 01:38)
 

CREATE TABLE `contest` (
`id_contest` INT(8) NOT NULL AUTO_INCREMENT,
`author` TINYTEXT NOT NULL,
`email` TINYTEXT,
`titleph` TINYTEXT,
`small` TINYTEXT NOT NULL,
`big` TINYTEXT NOT NULL,
`hide` ENUM('show','hide') NOT NULL DEFAULT 'hide',
`quote` INT(10) NOT NULL DEFAULT '0',
`date` DATETIME DEFAULT '0000-00-00 00:00:00',
`id_contest_cat` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id_contest`)
)ENGINE=MyISAM DEFAULT CHARSET=cp1251;

CREATE TABLE `contest_cat` (
`id_contest_cat` INT(8) NOT NULL AUTO_INCREMENT,
`name` TINYTEXT NOT NULL,
`description` TEXT NOT NULL,
`hide` ENUM('show','hide') NOT NULL DEFAULT 'hide',
`data` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id_contest_cat`)
)ENGINE=MyISAM DEFAULT CHARSET=cp1251;

  Ответить  
 
 автор: Trianon   (17.12.2009 в 02:02)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 01:55)
 

Спасибо. Замечательно.
Дамп данных делается в phpMyAdmin на закладке Экспорт.
Прикрепить лучше архивом.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 02:16)   письмо автору
1.3 Кб
 
   для: Trianon   (17.12.2009 в 02:02)
 

Это не дамп, Вас не устроил "чертёж", вот и прикрепил структуру.
теперь прикрепил дамп.
изменил запрос, как посоветовали, теперь выводит по одной фото из каждой группы, но значения quote не соответсвуют фотографиям.
группировал по id_contest_cat

p.s. удалил из дампа одну таблицу, которая не имеет отношения к вопросу

а вот с базой по моему проблемка есть, после Вашей просьбы сделать дам рассмотрел одну фигню....
в таблице contest primary key есть , вот key не указан мной ...

  Ответить  
 
 автор: Trianon   (17.12.2009 в 02:37)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 02:16)
 

>Это не дамп, Вас не устроил "чертёж", вот и прикрепил структуру.
Всё правильно. Я структуру и просил сперва. И дамп тоже. Потом.
На будущее. Когда описываете проблему со сложным запросом - с этого надо начать.
Так прямо и написать. Дамп структуры и данных прикрепляю.

>теперь прикрепил дамп.
>изменил запрос, как посоветовали,
И где он , этот свежий вариант? Который
теперь выводит по одной фото из каждой группы, но значения quote не соответсвуют фотографиям.

Показывайте.
Напомню:
напишите простой запрос, в котором Вы вытаскиваете группирующее значение и значения агрегатных функций. И всё.
Следующий шаг - потом.

>группировал по id_contest_cat

То есть так всё же не по quote. Уже хорошо.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 02:46)   письмо автору
 
   для: Trianon   (17.12.2009 в 02:37)
 

Запрос
SELECT `id_contest`, MAX(`quote`) FROM `contest` GROUP BY `id_contest_cat` LIMIT 3
Выводит
1-я группа
id_contest = 62 (64)
MAX(`quote`) = 10
2-я группа
id_contest = 67 (55)
MAX(`quote`) = 2
3-я группа
id_contest = 68 (56)
MAX(`quote`) = 2
в скобках указаны значения id_contest которые должны быть при получении результатов запроса

  Ответить  
 
 автор: Trianon   (17.12.2009 в 02:56)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 02:46)
 

Я же вроде пояснил, что id_contest в списке SELECT быть не должно. Только группирующие поля (это у вас `id_contest_cat` - он один в GROUP BY) и агрегаты ( это у Вас MAX(`quote`) )
И никаких лимитов. Все сортировки лимиты и прочие фенечки ПОЗЖЕ!!!!

Итак (я добавил алиас для удобства):
SELECT `id_contest_cat`, MAX(`quote`) AS`maxquote`
  FROM `contest` 
  GROUP BY `id_contest_cat` 

Вас устраивает вывод этого запроса по данным? Он правильно считает?
id_contest_cat     maxquote
          15          10
          16          2
          17          2

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 03:03)   письмо автору
 
   для: Trianon   (17.12.2009 в 02:56)
 

проверил, считает правильно
вот как теперь привязать id_contest к этому?

  Ответить  
 
 автор: Trianon   (17.12.2009 в 03:09)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 03:03)
 

Теперь, когда агрегаты посчитаны, рассказывайте, какие еще поля у каких таблиц Вы хотели получить.
Кроме номера категории и максимума quote для этой категории. Слово группа (хоть у Вас сущность так называется) не применяю, дабы не вносить терминологическую путаницу.
Какая именно из id_contest нужна для каждой из трех строк и почему?

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 03:21)   письмо автору
 
   для: Trianon   (17.12.2009 в 03:09)
 

из таблицы contest_cat надо получить id_contest_cat и name, для того, что бы вывести название группы, а потом передать эти значения методом get, сортировать надо по полю hide

из таблицы contest надо получить small, quote, titleph, сортировать по полю hide

для каждой строки нужна та id_contest которой соответсвует максимальное quote, опять же для передачи методом get на другую страницу где выводятся все фотографии группы, что бы отдельно от всех фото разместить фото лидера.

вот ссылка для наглядности.

  Ответить  
 
 автор: Trianon   (17.12.2009 в 03:31)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 03:21)
 

>из таблицы contest_cat надо получить id_contest_cat и name, для того, что бы вывести название группы, а потом передать эти значения методом get

C этим просто. LEFT JOIN результата с таблицей contest_cat по условию равенства ключей и вытаскивайте что хотите.

>из таблицы contest надо получить small, quote, titleph
Вы пока что даже первичный ключ (id_contest) не получили, а уже за остальными гонитесь.
С полем quote более менее ясно - это посчитанный по категориям максимум.
А какой именно id_contest ему соответствует?

            id_contest 
id_contest_cat         quote     
    15         64     10     
    15         62     9     
    15         63     2     
    16         55     2     
    16         66     1     
    16         67     0     
    17         56     2     
    17         65     1     
    17         68     0     

С 15-й категорией более менее понятно . фотография нужна с quote = 10 и она одна (64).
А 16 и 17 категории? Там как?

UPD. Хотя там тоже однозначно.
Но что Вы будете если будут две двойки в пределах одной категории - что делать?
представьте, что строка 16 - 66 тоже набрала двойку.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 03:50)   письмо автору
 
   для: Trianon   (17.12.2009 в 03:31)
 

все id_contest соответствуют quote

15 надо получить id_contest 64
16 ----------------//----------------- 55
17 ----------------//----------------- 56
вот эти три фото надо вывести на главной.

насчёт совпадения quote в одной категории я думал и как понимаю distinct тут не поможет.
наверное надо будет добавлять ещё одно поле в contest , голоса принимать от 1 до 5 и потом уже высчитывать среднее значение для каждой фото.
или есть варианты?

  Ответить  
 
 автор: Trianon   (17.12.2009 в 03:54)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 03:50)
 

Вы не с того конца думаете.
Забудьте на минуту про SQL.

Вы же там конкурс проводите.
Вот набирают два человека одно и то же (максимальное) число голосов.
Кого из них Вы покажете?
Что будете делать с лицом (своим), после того, как тот, кого из них Вы не покажете, Вам его набьет?

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



PS. Голос , кстати, по-аглицки не quote, а vote.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 04:11)   письмо автору
 
   для: Trianon   (17.12.2009 в 03:54)
 

>PS. Голос , кстати, по-аглицки не quote, а vote.
я в курсе, но это не главное :), написал сначала quote, а потом не стал исправлять, так и осталось.

>Вот набирают два человека одно и то же (максимальное) число голосов.

значит надо всётаки добавлять одно поле в таблицу, и диапозон при голосовании делать от 1 до 5...
или, например, добавлять время голосования и тогда уже по времени выбирать лидера, за кого последнего проголосовали, то и лидер...

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 04:37)   письмо автору
 
   для: Trianon   (17.12.2009 в 03:54)
 

Trianon, спасибо, что то начало получаться, но додумаю завтра....

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 15:17)   письмо автору
 
   для: Trianon   (17.12.2009 в 03:31)
 

рано обрадовался :(
с таблицей contest_cat действительно без проблем, все нужные значения получил, а вот с таблицей contest ни как не могу разобраться, не пойму как получить нужные значения id_contest , small, titleph

SELECT `con2`.`id_contest_cat`,
              MAX(`con2`.`quote`) AS `mquote`,
                  `con1`.`name` AS `name`,
                  `con2`.`titleph` AS `title`,
                  `con2`.`id_contest` AS `id_us`
             FROM `contest` AS `con2`
        LEFT JOIN `contest_cat` AS `con1` ON `con1`.`id_contest_cat` = `con2`.`id_contest_cat`
            GROUP BY `id_contest_cat`

вот что я накрутил, но ....

  Ответить  
 
 автор: Trianon   (17.12.2009 в 18:48)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 15:17)
 

исправляйте. Учитывая сказанное (16.12.2009 в 14:10) и по ссылке в (16.12.2009 в 15:41)

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 19:41)   письмо автору
 
   для: Trianon   (17.12.2009 в 18:48)
 

хорошо, вот запрос

SELECT `contest`.`id_contest_cat`,
              MAX(`contest`.`quote`) AS `mquote`,
                  `contest`.`id_contest` AS `id_contest`,
                  `contest_cat`.`name` AS `name`
             FROM `contest_cat`
        LEFT JOIN `contest` ON `contest`.`id_contest_cat` = `contest_cat`.`id_contest_cat`
            GROUP BY `id_contest_cat`

при таком запросе у меня выводит правильно название группы фотографий и quote, хотя если следовать Вашим рекомендациям от 16.12.09 в 14.10, то получается, что `contest_cat`.`name` AS `name` я не могу писать, т.к. оно ни где не присутствует, ни в группирирующих ни в агрегатной, но это всёравно мне даёт имя группы фотографий.
если я допишу в GROUP id_contest, то будет вывод всех фотографий.
я не могу понять как всё таки получить id_contest для извлечения остальных полей нужной фотографии,самого изображения, названия...?

  Ответить  
 
 автор: Trianon   (17.12.2009 в 20:15)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 19:41)
 

>хорошо, вот запрос
>

>SELECT `contest`.`id_contest_cat`,
>              MAX(`contest`.`quote`) AS `mquote`,
>                  `contest`.`id_contest` AS `id_contest`,
>                  `contest_cat`.`name` AS `name`
>             FROM `contest_cat`
>        LEFT JOIN `contest` ON `contest`.`id_contest_cat` = `contest_cat`.`id_contest_cat`
>            GROUP BY `id_contest_cat`
>


Что хорошо, что?

Сказал же: В списке селект агрегатного запроса не должно присутствовать ничего кроме того, что в GROUP BY, и того что внутри MAX() !
Трижды уже сказал, если не больше!!
Почему появилось еще два поля, которые этому условию не отвечают?!

Отдельный вопрос. Почему поле в GROUP BY не уточнено именем таблицы?

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 20:38)   письмо автору
 
   для: Trianon   (17.12.2009 в 20:15)
 

значит правильно понял, не должно присутствовать, но подставив в запрос `contest_cat`.`name` AS `name` - получил имя группы фотографий, это первое, что я не могу понять.
прочитал по Вашей ссылке, рылся в мануале, но так и не смог понять как вытянуть остальные параметры. с чем связать contest.id_contest что бы вытянуть из таблицы и уже к этому привязывать остальные параметры?
поле в GROUP уточнил именем таблицы contest_cat

возможно надо сделать к таблице contest вложеный запрос? или я опять не туда думаю?

  Ответить  
 
 автор: Trianon   (17.12.2009 в 21:20)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 20:38)
 

>значит правильно понял, не должно присутствовать, но подставив в запрос `contest_cat`.`name` AS `name` - получил имя группы фотографий, это первое, что я не могу понять.

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

Почему в некоторых - потому что в случаях однозначной ключевой зависимости от группирующего поля.
У Вас `contest_cat`.`name` (точнее все поля таблицы `contest_cat`) однозначно определяется первичным ключом этой таблицы, по которому и идет группировка. Вот поэтому с этим полем всё хорошо. А с остальными плохо. Потому что ключевой зависимости нет.

Почему MySQL - потому что любой другой нормальный SQL-сервер такой запрос отвергнет, как ошибочный, и чихать ему на зависимости. Писать запросы нужно корректно.
Вам сейчас нужно научиться писать запросы в строгом виде, невзирая на ключевые зависимости.
Научитесь писать строго - писать попроще всегда сможете. Поэтому `contest_cat`.`name` убирайте, несмотря на то, что с ним все Ок.

>поле в GROUP уточнил именем таблицы contest_cat

Уже лучше.


>прочитал по Вашей ссылке, рылся в мануале, но так и не смог понять как вытянуть остальные параметры. с чем связать contest.id_contest что бы вытянуть из таблицы и уже к этому привязывать остальные параметры?

Ограничения о которых мы сейчас говорим - это ограничения только для агрегатных запросов.
Обычные запросы таких ограничений не имеют.

Агрегатный запрос вернул Вам таблицу из двух столбиков.
Эту таблицу можно использовать как исходную таблицу в другом - сложном запросе.
Сложный запрос уже без GROUP BY и MAX() - агрегатным уже не будет. Таких ограничений иметь не будет. И в него можно натолкать любых нужных таблиц, из которых извлечь нужные поля.
Таблицы, конечно, нужно соединить. Это и проиллюстрировано по ссылке.

>возможно надо сделать к таблице contest вложеный запрос?
Не вложенный, а наоборот - объемлющий.
Вложенным будет агрегатный, уже написанный и отлаженный.

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 21:39)   письмо автору
 
   для: Trianon   (17.12.2009 в 21:20)
 

>Таблицы, конечно, нужно соединить. Это и проиллюстрировано по ссылке.
это до меня тоже дошло, не дошло как это сделать.

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

получается что то типа

SELECT * FROM(агрегатный запрос) AS q
LEFT JION contest AS con ON q.quote = con.quote

по моему бред несу....

  Ответить  
 
 автор: Trianon   (17.12.2009 в 22:33)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 21:39)
 

никакой не бред. Именно так. при этом таблица q - это результат работы вложенного (агрегатного, в данном случае) запроса.

только ON q.mquote = con.quote
Поскольку в агрегатном запросе у Вас алисасом столбик назван именно mquote

  Ответить  
 
 автор: Slo_Nik   (17.12.2009 в 23:33)   письмо автору
 
   для: Trianon   (17.12.2009 в 22:33)
 

вот что получилось
SELECT `con`.`small` AS `small`,
                  `con`.`titleph` AS `title`,
                  `con`.`id_contest` AS `id_us`,
                  `con`.`quote` AS `quote`,
                  `con`.`id_contest_cat` AS `id_con`
                  
             FROM (SELECT `contest`.`id_contest_cat`,
                      MAX(`contest`.`quote`) AS `mquote`
                     FROM `contest`
                LEFT JOIN `contest_cat` ON `contest`.`id_contest_cat` = `contest_cat`.`id_contest_cat`
                 GROUP BY `contest_cat`.`id_contest_cat`) AS `q`
             LEFT JOIN `contest` AS `con` ON (`con`.`quote` = `q`.`mquote`)
             
             LIMIT 3

получаю

small - 20091215154719_s.jpg
title - третий первого
id_us - 64
quote - 10
id_con - 15
small - 20091215102932_s.jpg
title - первый третьего
id_us - 56
quote - 2
id_con - 17
small - 20091215102639_s.jpg
title - первый второго
id_us - 55
quote - 2
id_con - 16

то что надо, но.................
если мне надо получить имя группы фотографий, то как я понял, мне надо дописать в запрос вот это

SELECT..............
`con2`name` AS `name`,
`con2`.`id_contest_cat` AS `id_con2`
FROM(................................)
LEFT JOIN..................................
LEFT JOIN `contest_cat` AS `con2` ON `con2`.`id_con2` = `q`.`id_contest_cat`

и получаю ошибку
mysql_fetch_assoc(): supplied argument is not.............

опять что то не так сделал?

исправил ошибку, применил в условии ON алиас поля, вот и полезла ошибка.

  Ответить  
 
 автор: Trianon   (18.12.2009 в 08:31)   письмо автору
 
   для: Slo_Nik   (17.12.2009 в 23:33)
 

>

>SELECT..............
>`con2`name` AS `name`,
>`con2`.`id_contest_cat` AS `id_con2`
>FROM(................................)
>LEFT JOIN..................................
>LEFT JOIN `contest_cat` AS `con2` ON `con2`.`id_con2` = `q`.`id_contest_cat`
>

>и получаю ошибку
>mysql_fetch_assoc(): supplied argument is not.............
>
>опять что то не так сделал?
>
>исправил ошибку, применил в условии ON алиас поля, вот и полезла ошибка.

`con2`name` AS `name`, - это что означает? По-моему в чистом виде синтаксическая ошибка.
не надо лепить LEFT JOIN внутрь агрегатного запроса - он и без того тяжел.
Ошибки следует исправлять не методом тыка, а читая диагностики.
>mysql_fetch_assoc(): supplied argument is not - это не диагностика.
Это сообщение о том , что после исполнения запроса, Вы не проверили результат, и не остановили скрипт сами, выведя диагностику из mysql_error().

  Ответить  
 
 автор: Slo_Nik   (18.12.2009 в 20:25)   письмо автору
 
   для: Trianon   (18.12.2009 в 08:31)
 

>Ошибки следует исправлять не методом тыка, а читая диагностики.
>mysql_fetch_assoc(): supplied argument is not - это не диагностика.
>Это сообщение о том , что после исполнения запроса, Вы не проверили результат, и не >остановили скрипт сами, выведя диагностику из mysql_error().

да, действительно у меня нет проверки результата запроса, вернее она ест, но после запроса
if(!$con) echo "......".mysql_error();
т.е. у меня нет or die();

>`con2`name` AS `name`, - это что означает? По-моему в чистом виде синтаксическая ошибка.
ошибка , но уже всё исправил, работает.

>не надо лепить LEFT JOIN внутрь агрегатного запроса - он и без того тяжел.

посмотрел внимательней на код, и LEFT JOIN убрал потому, что объеденения ни какого не происходит.
или я не прав?

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

если надо применять в запросе агрегатные функции, то это запрос всегда делать вложенным или всё зависит от конкретной задачи?

  Ответить  
 
 автор: Trianon   (18.12.2009 в 20:36)   письмо автору
 
   для: Slo_Nik   (18.12.2009 в 20:25)
 

Вложенным надо делать запрос, если без этого, не нарушая правило неоднозначности (которое пятый раз я цитировать не буду) все поля не достать.
И Вы смотрите на запрос со стороны выхлопной трубы.
Не делать вложенным, а подсоединять нужные таблицы, путем обертывания снаружи.
Да-да-да! JOIN - это соединение, а не объединение.

касательно "нет die()"
Если Вы знаете, что запрос не прошел - зачем продолжать выполнение скрипта?

if(!$con) очевидно проверяет не запрос, а подключение к серверу.

  Ответить  
 
 автор: Slo_Nik   (18.12.2009 в 00:54)   письмо автору
 
   для: Trianon   (17.12.2009 в 22:33)
 

Спасибо за помощь, всё работает:):):)

  Ответить  
 
 автор: Slo_Nik   (22.12.2009 в 20:14)   письмо автору
 
   для: Slo_Nik   (18.12.2009 в 00:54)
 

Прийдётся вернуться к теме... поспешил с выводами.
Запрос работает, но есть одно "но".
схема осталась та же, три группы фотографий, надо вывести названия всех трёх групп и для каждой одно фото, с максимальным кол-вом голосов.
Всё так и выводится, но только тогда, когда для всех фото есть голоса, а если только создать группы, загрузить фото и кол-во голосов будет у всех фото "0", то запрос перестаёт нормально работать.
Начинает выводится две группы, для одной две позиции, для другой одна.
стоит только для одной фотографии в любой группе поставить хотя бы один голос, всё нармально работает...
я так понял, что проблема в этой части запроса

LEFT JOIN `contest` AS `con` ON (`con`.`quote` = `q`.`mquote`) 
ORDER BY `con`.`quote` DESC           
LIMIT 3

но ни как не могу сообразить, как отсортировать данные, если кол-во голосов у всех фото равны?

  Ответить  
 
 автор: Лена   (22.12.2009 в 23:00)   письмо автору
 
   для: Slo_Nik   (22.12.2009 в 20:14)
 

Вы выводите для каждой группы одну фотографию с максимальным количеством голосов.
Допустим, у каждого из фото количество голосов "0". Как можно из кучи нолей выбрать максимум?
Вам в запросе нужно тогда поставить условие: если quote = 0, то или вообще не выбираем ничего, или выбираем фото с наибольшим(наименьшим) id. Вы что хотите вывести?
Приведите, пожалуйста, сам запрос, который у вас получился.

  Ответить  
 
 автор: Slo_Nik   (22.12.2009 в 23:09)   письмо автору
 
   для: Лена   (22.12.2009 в 23:00)
 

сам запрос

SELECT `con`.`small` AS `small`,
                  `con`.`titleph` AS `title`,
                  `con`.`id_contest` AS `id_us`,
                  `con`.`id_contest_cat` AS `id_con_us`,
                  `con`.`quote` AS `quote`,
                  `cont`.`id_contest_cat` AS `id_cont`,
                  `cont`.`name` AS `name`
             FROM (SELECT `contest`.`id_contest_cat`,
                      MAX(`contest`.`quote`) AS `mquote`
                     FROM `contest`
                 GROUP BY `contest`.`id_contest_cat`) AS `q`
             LEFT JOIN `contest` AS `con` ON (`q`.`mquote` = `con`.`quote`)
             LEFT JOIN `contest_cat` AS `cont` ON (`cont`.`id_contest_cat` = `con`.`id_contest_cat`)
             ORDER BY `con`.`quote` DESC
             LIMIT 3

этот запрос нормально работает, когда у всех фото или практически у всех есть голоса, т.е. quote не равно "0". тогда на главной странице выводится название для каждой группы и одно фото с максимальным quote для определённой группы.
если quote равно "0" у всех фото, тогда выводятся всего 2-е группы, для одной группы две позиции на странице, для другой одна.
получается, что если quote = "0", то надо будет сортировать по id сами фото,
если взять из запроса ту часть, где определяется максимальное quote, то даже с нулевым значением выводятся все группы.

  Ответить  
 
 автор: Лена   (23.12.2009 в 00:09)   письмо автору
 
   для: Slo_Nik   (22.12.2009 в 23:09)
 

У вас по ссылке, которую привели выше, три группы, в каждой группе - фото с максимальным quote.
Я вам пыталась постом выше сказать: допустим, в каждой группе все фото с quote = "0". Еще понятнее. Группа 1. Самая левая. В ней, допустим, у вас три фото. У каждого фото quote = "0". И вы хотите из этих quote выбрать максимум. Это невозможно.
Вот есть у вас три вещи. Каждая из них стоит, допустим, 100 грн. Вы можете выбрать из этих трех вещей ту, которая больше всего стоит? У вас три цифры: 100, 100, 100 - можно из них максимум выбрать? Точно так же и с нолями.
У вас проблема не в LEFT JOIN `contest`, а в основной таблице, к которой соединяются столбцы из других таблиц.
Основная таблица SELECT `contest`.`id_contest_cat`, MAX(`contest`.`quote`)... не сможет из нолей выбрать максимум. А значит SQL вам подсунет какую-то ерунду. Мне так, по крайней мере кажется.
Поэтому вы должны решить: если у вас все quote = "0", вам или внутри этого запроса влепить условие исполнять его только, если quote != "0", или как-то по-другому... Подумаю, завтра на свежую голову скажу, уже спать хочется.

  Ответить  
 
 автор: Slo_Nik   (23.12.2009 в 09:55)   письмо автору
 
   для: Лена   (23.12.2009 в 00:09)
 

смотрите, что получается.
проблема в том, что если quote равно "0", группы фотографий выводятся не по порядку, 1 , 2 , 3, а, например, 2 , 2 , 1. всего надо три группы вывести, да их и будет всего три.
если сделать простой запрос, как писал выше Trianon, то при подсчёте max quote,даже если quote = "0", группы выводятся как положено, 1 , 2 , 3.
вот эта часть запроса, через id_contest_cat связвываются две таблицы.

(SELECT `contest`.`id_contest_cat`,
        MAX(`contest`.`quote`) AS `mquote`
     FROM `contest`
GROUP BY `contest`.`id_contest_cat`) AS `q`

этот запрос нужен для того, что бы для каждой группы вывести одну фотографию с макс. quote.
делаю простой запрос для получения списка групп фотографий

SELECT
                  `contest_cat`.`id_contest_cat` AS `id_cont`,
                  `contest_cat`.`name` AS `name`
     FROM `contest_cat`

получаю вывод всех трёх групп как и положено, 1 , 2 , 3, всё совпадает, имена групп соответствуют id групп.

теперь когда объеденяю эти два запроса(пример запроса выше), получается, что весь вывод ломается, группы выводятся не по порядку, а, например, 2 , 2 , 1
вот вопрос в том, как сохранить порядок вывода групп?

  Ответить  
 
 автор: Лена   (23.12.2009 в 11:00)   письмо автору
 
   для: Slo_Nik   (23.12.2009 в 09:55)
 

Смотрите. Простой запрос,без максимума у меня выводит так:
17- Третий
15 - Первый
16 - Второй
Сложный запрос выводит категории так:
15 - Первый
17-Третий
16 - Второй.
А Вам как надо?

  Ответить  
 
 автор: Slo_Nik   (23.12.2009 в 11:13)   письмо автору
 
   для: Лена   (23.12.2009 в 11:00)
 

мне без разницы как будет выводится, главное, что бы выводились группы, все три, 15,16,17, а какой последовательности не важно.
ещё главное условие, что бы для каждой группы, выводилось одна фотография с макс. quote,а если quote = 0, то порядок вывода групп не нарушался.
вот до этого я пока додуматься не могу.

  Ответить  
 
 автор: Лена   (23.12.2009 в 11:32)   письмо автору
 
   для: Slo_Nik   (23.12.2009 в 11:13)
 

-

  Ответить  
 
 автор: Лена   (16.12.2009 в 13:52)   письмо автору
 
   для: Trianon   (16.12.2009 в 13:30)
 

Не заметила. Из-за того, что автор алиасов для таблиц не использует, трудно читать.

  Ответить  
 
 автор: Slo_Nik   (20.01.2010 в 00:30)   письмо автору
 
   для: Slo_Nik   (16.12.2009 в 12:57)
 

Много было в этой теме написано, много дельных советов, спасибо Trianon и Лена.
Для тех, кому интересно решение этой проблемы привожу запрос

"SELECT con.small AS small,
         con.titleph AS title,
         con.id_contest AS id_us,
         con.id_contest_cat AS id_con_us,
         con.quote AS mquote,
         cont.id_contest_cat AS id_cont,
         cont.name AS name
      FROM(select contest.id_contest_cat,
                     max(contest.id_contest) as id_contest
                    FROM(SELECT contest.id_contest_cat,
                            MAX(contest.quote) AS mquote
                           FROM contest
                       GROUP BY contest.id_contest_cat) AS cq
                      LEFT JOIN contest ON (cq.mquote = contest.quote) and (cq.id_contest_cat=contest.id_contest_cat)
                       GROUP BY contest.id_contest_cat) as q
        LEFT JOIN contest AS con ON (q.id_contest = con.id_contest)
        LEFT JOIN contest_cat AS cont ON (cont.id_contest_cat = con.id_contest_cat)
        ORDER BY con.quote DESC LIMIT 3"

Проверено, работает.

  Ответить  
 
 автор: Trianon   (20.01.2010 в 00:46)   письмо автору
 
   для: Slo_Nik   (20.01.2010 в 00:30)
 

На самом деле, весьма желательно эту тему переименовать в
"Как получить из таблицы строку с максимальным значением поля?"
Вопрос такой поднимается довольно часто, подводных камней у него масса.
А тут где-то как-то даже подход нарисовался...

  Ответить  
 
 автор: Slo_Nik   (20.01.2010 в 01:03)   письмо автору
 
   для: Trianon   (20.01.2010 в 00:46)
 

Да я не против, пусть как хотят переименовывают, конечно если это принесёт пользу.
Но тогда надо отредактировать её, убрать лишнее....
Но я думаю, что предложеное название не совсем точно...

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

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