За последние 24 часа нас посетили 34252 программиста и 1749 роботов. Сейчас ищут 1012 программистов ...

Выборка самых ранних сообщений

Тема в разделе "MySQL", создана пользователем mkramer, 28 мар 2017.

  1. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Что-то не могу придумать запросик. Вот есть примерно такая схема
    Код (Text):
    1.  
    2. create table dialogs (
    3.   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    4.    PRIMARY KEY (`id`)
    5. ) ENGINE=InnoDB;
    6.  
    7. CREATE TABLE `messages` (
    8.  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    9.   `dialog_id` int(11) NOT NULL,
    10.  `text` text COLLATE utf8mb4_unicode_ci NOT NULL,
    11.   `created_at` timestamp NULL DEFAULT NULL,
    12.    PRIMARY KEY (`id`)
    13. ) ENGINE=InnoDB;
    14.  
    15. insert into dialogs set id = 1;
    16. insert into dialogs set id = 2;
    17.  
    18. insert into messages set dialog_id=1, `text`='hello 1.1', created_at = '2017-03-28 10:20:00';
    19. insert into messages set dialog_id=1, `text`='hello 1.2', created_at = '2017-03-28 10:21:00';
    20. insert into messages set dialog_id=2, `text`='hello 2.1', created_at = '2017-03-27 10:30:00';
    21. insert into messages set dialog_id=2, `text`='hello 2.2', created_at = '2017-03-27 10:31:00';
    http://sqlfiddle.com/#!9/8c3c28 - но там что-то на sql-fiddle не работает, там 504-ая с ajax-запросами.

    Так вот. Можно ли выбрать одним запросам только самые ранние сообщения по каждому dialog_id? Мне пока в голову приходит только вложенный подзапрос, но может можно позже?
     
  2. Drema

    Drema Новичок

    С нами с:
    20 фев 2017
    Сообщения:
    117
    Симпатии:
    30
    Подзапрос - вполне нормальное решение, вы чего его так боитесь? :)
     
  3. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Нормальное, но не лучшее. Это будет вычисляться много запросов в одном, мне не нравится. Может кто-то предложит лучше. Если нет - сделаю подзапрос или денормализую таблицы
     
  4. Drema

    Drema Новичок

    С нами с:
    20 фев 2017
    Сообщения:
    117
    Симпатии:
    30
    В такой задаче выбирать лучше или не лучше не приходится :)

    Код (Text):
    1. SELECT *
    2. FROM messages m1
    3. WHERE (m1.dialog_id, m1.created_at) = (
    4.   SELECT m2.dialog_id, MIN(m2.created_at)
    5.   FROM messages m2
    6.   GROUP BY m2.dialog_id
    7. )
     
    artoodetoo нравится это.
  5. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.866
    Симпатии:
    753
    Адрес:
    Татарстан
    лучшее - враг хорошего! )))
     
  6. acho

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

    С нами с:
    28 дек 2016
    Сообщения:
    854
    Симпатии:
    210
    Адрес:
    Санкт-Петербург
    @Drema, а ты проверял свой запрос то? Есть ощущение, что он выдаст ошибку.
     
  7. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.817
    Симпатии:
    1.333
    Адрес:
    Лень
    MIN(m2.created_at) min_created
     
  8. retvizan

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

    С нами с:
    27 дек 2013
    Сообщения:
    68
    Симпатии:
    22
    есть как минимум 5 способов, см http://sqlinfo.ru/articles/info/18.html
    (второй, кстати, без так нелюбимых вами подзапросов)

    на практике, бывает оправдана денормализация, например, б.д. форума может хранить последнее сообщение для каждого раздела
     
    artoodetoo нравится это.