За последние 24 часа нас посетили 20304 программиста и 1713 роботов. Сейчас ищут 1780 программистов ...

Как составить запрос с сортировкой и отсеиванием?

Тема в разделе "PHP и базы данных", создана пользователем colaa, 7 июн 2010.

  1. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    вот у меня есть таблица
    some_table
    в которой есть 3 поля:
    id, item_id, date

    1 1 1000
    2 1 5001
    3 2 1245
    4 2 8723
    5 3 3462
    6 1 2222

    Нужно получить список элементов отсортированных по дате, но что бы элементы не повторялись
    отображает список уникальных элементов отсортированных по дате в котором для каждого элемента дата самая последняя (наибольшая)

    4 2 8723
    5 3 3462
    2 1 5001


    Я очень извиняюсь возможно плохо изложил вопрос, но я уже мозг поломал.
     
  2. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    перечитал и самому теперь плохо понятно. Вот ещё, как вариант:

    есть та же самая таблица
    id, item_id, date
    1 1 1000
    2 1 5001
    3 2 1245
    4 2 8723
    5 3 3462
    6 1 2222

    сортируем её по дате в обратном порядке

    4 2 8723
    2 1 5001
    5 3 3462
    6 1 2222
    3 2 1245
    1 1 1000

    и теперь выбираем каждое первое уникальное вхождение item_id

    4 2 8723
    2 1 5001
    5 3 3462

    вот это мне надо получить

    пожалуйста подскажите, очень надо
     
  3. Scorpius

    Scorpius Активный пользователь

    С нами с:
    6 май 2010
    Сообщения:
    59
    Симпатии:
    0
    Адрес:
    там уже нет
    [sql]
    SELECT DISTINCT item_id FROM table ORDER BY date DESC
    [/sql]
     
  4. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    уже пробовал, но это не то что мне надо
    данный запрос сначала выбирает уникальные а потом сортирует их по дате, и в результатах у меня не то что надо
    то же самое если делать

    [sql]SELECT * FROM table GROUP BY item_id ORDER BY date DESC[/sql]
     
  5. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    [sql]SELECT MAX(id) FROM table GROUP_BY item_id[/sql]
    Остальную информацию извлекать по списку этих ID

    Есть еще такой вариант
    [sql]SELECT * FROM table GROUP BY item_id
    HAVING id = MAX(id)[/sql]
     
  6. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    Тоже выдаёт не то =((((


    кстати, нашёл "уродский" способ получить то что мне надо, только вот он ОЧЕНЬ тяжёлый и это 100% не выход

    сначала сортирую всю таблицу по дате
    [sql]ALTER TABLE `table` ORDER BY `date` DESC[/sql]

    а потом выбираю уникальные значения

    [sql] SELECT DISTINCT `item_id` FROM `table`[/sql]

    результат, который нужен, но это совершенно не подходит.



    и по понятным причинам я не могу сделать key-ем поле с датой,
    а когда добавляю новые строки в таблицу, то они просто вписываются в конец нарушая порядок

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

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Это невозможно.
    Строго говоря при DISTINCT и GROUP BY MySQL для неодинаковых значений столбцов в группе может выдать любое из них.

    Сделайте как я писал, сначала выберите
    SELECT MAX(id) FROM table GROUP_BY item_id

    затем выберите нужную информацию по этим записям.
    Если MAX(id) не соответствует MAX(date) а нужна сортировка именно по дате, то выбрать соответственно ее
    и сделать джойн на эту же таблицу опять для получения id
     
  8. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    [sql]SELECT MAX(date_c) FROM some GROUP_BY item_id[/sql]
    это выдавало не то что надо, и "не таким" был именно idшник

    теперь сделал с JOINом, но проблема осталась такой же =((

    [sql]SELECT MAX( s.date_c ) AS 'date', s2.id, s.item_id, s2.date_c
    FROM some AS s
    JOIN some AS s2
    WHERE s2.date_c = s.date_c
    GROUP BY s.item_id
    ORDER BY s.date_c DESC
    LIMIT 0 , 30[/sql]

    или

    [sql]SELECT MAX( s.date_c ) AS 'date', s2.id, s.item_id, s2.date_c
    FROM some AS s
    JOIN some AS s2 ON s2.date_c = s.date_c
    GROUP BY s.item_id
    ORDER BY s.date_c DESC
    LIMIT 0 , 30[/sql]

    s.date_c и item_id правильные, а вот idшники выдаёт те, которые соответсвуют первым вхождениям в таблице
    ну и конечно же s2.date кривые =\

    может быть я неправильно JOIN использую?
     
  9. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Значит обращаю внимание на следующие вещи.

    1. дата не идентифицирует однозначно запись.
    2. у записи есть 3 поля - id (уникальный вообще в таблице), item_id, date_c

    Что нужно?
    Нужно выбрать запись id, item_id, date_c

    Если мы будем выбирать только по date_c, то мы получим кучу разных записей с разным item_id
    Это несколько не то, что надо.
    Поэтому при условии что для каждого item_id date_c не повторяется, мы можем однозначно определить запись по этим двум полям.

    Соответственно при выборке с группировкой, нам нужно выбирать не только MAX(date_c), но и сам item_id к которому принадлежит этот date_c
    И дальше JOIN делать по условию на 2 этих поля, а не на одно date_c

    Ну и форма записи JOIN такова

    [sql]SELECT поля FROM таблица
    JOIN таблица ON условия(т.е. неравенств тут может быть несколько соединенных логическими операторами) [/sql]
     
  10. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    Ругается, если я пишу:

    [sql]ON s.item_id = s2.item_id AND s2.date_c = MAX(s1.date_c)[/sql]
    и насколько я понимаю нельзя использовать MAX(s1.date_c) в ON

    а если просто пишу
    [sql]ON s.item_id = s2.item_id AND s2.date_c = s1.date_c[/sql]
    выдаёт неправильные результаты

    и скорее всего потому что тут проблема
    [sql]SELECT MAX( date_c ) , date_c
    FROM some
    GROUP BY item_id
    LIMIT 0 , 30[/sql]

    результаты, которые возвращает запрос противоречат здравому смыслу, потому что в первой и второй колонке данные различаются

    и в первой, действительно то что мне надо, а во второй первые вхождения item_id


    и есть другая проблема, не нужно получить не пары item_id - date_c
    а именно id-шники
     
  11. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    ставим алиас, как уже делали выше
    и в
    используем именно алиас, а не MAX()

    id надо брать из 2й таблицы, той которая будет джойниться.
     
  12. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    если я вас понял, то в упрощённом варианте должно быть, что то подобное:
    [sql] SELECT MAX( date_c ) AS 'hehe', date_c
    FROM some
    WHERE date_c = hehe
    GROUP BY item_id
    LIMIT 0 , 30 [/sql]

    и соответственно ошибка:[sql]Unknown column 'hehe' in 'where clause' [/sql]

    я только недавно полез в SQL, так что многого не знаю, если вам не сложно, то пишите чуточку подробнее(как для чайнков) =)
     
  13. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    В упрощенном виде это работать не будет.

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

    примерно так

    [sql]SELECT t.alias FROM (SELECT field as alias FROM table) as t[/sql]
    и дальше JOIN с исходной table

    Чуточку подробнее это готовый код.
    Поэтому давайте разбираться в таком варианте. Как только вы поймете механику - все будет очень просто.
     
  14. Volt(220)

    Volt(220) Активный пользователь

    С нами с:
    11 июн 2009
    Сообщения:
    1.640
    Симпатии:
    1
    Я вижу 2 варианта:
    1) а) Приведенный ранее но чуть измененный "SELECT MAX( date_c )... GROUP BY item_id." И джойнить к нему выборку id.
    б) Вывернуть на лицевую сторону предыдущий запрос.
    2) Запрос со связанным подзапросом.
     
  15. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    [sql]SELECT t.max_date, s.item_id, s.id
    FROM (

    SELECT MAX( date_c ) AS max_date
    FROM some
    ) AS t
    JOIN some AS s ON t.max_date = s.date_c
    GROUP BY s.item_id
    ORDER BY s.date_c DESC
    LIMIT 0 , 30[/sql]

    выдаёт нужную строку, НО (!) только одну =(
    где я опять напортачил?




    а можно по-подробней?
     
  16. Simpliest

    Simpliest Активный пользователь

    С нами с:
    24 сен 2009
    Сообщения:
    4.511
    Симпатии:
    2
    Адрес:
    Донецк
    Группировка должна быть в подзапросе, а не в JOIN, ведь мы же хотим выбрать список item_id с нужной нам датой.

    В запросе с JOIN уже будут исключительно нужные значения.
     
  17. colaa

    colaa Активный пользователь

    С нами с:
    30 май 2010
    Сообщения:
    9
    Симпатии:
    0
    теперь всё работает так как надо!
    огромнейшее спасибо за помощь!!!!!