За последние 24 часа нас посетил 18091 программист и 1599 роботов. Сейчас ищут 917 программистов ...

Хитрый запрос с сортировкой

Тема в разделе "MySQL", создана пользователем nickstop, 14 май 2014.

  1. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Всем привет!
    Не знаю, как составить хитрый запрос с сортировкой. Более подробно ниже.

    Есть две таблицы:
    Код (Text):
    1. CREATE TABLE IF NOT EXISTS `products` (
    2.   `id` int(11) NOT NULL AUTO_INCREMENT,
    3.   `title` varchar(255) NOT NULL,
    4.   `description` varchar(255) NOT NULL,
    5.   `l` varchar(255) NOT NULL,
    6.   `d` varchar(255) NOT NULL,
    7.   `s` varchar(255) DEFAULT NULL,
    8.   `status` varchar(255) DEFAULT NULL,
    9.   `datecreate` datetime DEFAULT NULL,
    10.   PRIMARY KEY (`id`),
    11.   UNIQUE KEY `title_UNIQUE` (`title`),
    12. ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
    Код (Text):
    1. CREATE TABLE IF NOT EXISTS `orders` (
    2.   `id` int(11) NOT NULL AUTO_INCREMENT,
    3.   `datecreate` datetime DEFAULT NULL,
    4.   `products_id` int(11) DEFAULT NULL,
    5.   `users_id` int(10) unsigned NOT NULL,
    6.   `description` text,
    7.   `paid` tinyint(1) DEFAULT '0',
    8.   `price` decimal(10,2) DEFAULT NULL,
    9.   PRIMARY KEY (`id`),
    10.   KEY `fk_orders_users_id` (`users_id`)
    11.   KEY `fk_orders_products_id` (`products_id`)
    12. ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
    Чтобы выводить постранично предварительно перемешав - с этим я разобрался след. образом:
    Код (Text):
    1.  
    2. SELECT
    3.  `products`.`id`,
    4.  `products`.`title`,
    5.  `products`.`description`,
    6.  `products`.`detecreate`,
    7.   *произ.число* AS `ord`,
    8. FROM `products`
    9. WHERE `products`.`datecreate` IS NOT NULL
    10. ORDER BY RAND(ord) ASC LIMIT 20 OFFSET 0 (1)
    ,

    А как сделать, чтобы позиции которые "оплачены" (имели статус paid = true в orders) , всегда были первыми в постраничной выдачи, но так же между собой сортировались произвольно, подскажите идею или в каком направлении смотреть, буду очень признателен:)

    Маленький апдэйт.
    А как сделать, чтобы позиции которые "оплачены" (имели статус paid = true в orders) и оплачены менее месяца назад (т.е. CURRENT() < ADDDATE(orders.datecreate, INTERVAL 1 MONTH) ), всегда были первыми в постраничной выдачи, но так же между собой сортировались произвольно, подскажите идею или в каком направлении смотреть, буду очень признателен:)

    Не прошу готовый код, хотя не отказался бы от примерчика:)
     
  2. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ну попробуй
    ORDER BY `paid` DESC, RAND(ord) ASC
     
  3. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Спасибо за ответ:)
    В таком случае, как я понимаю, нужно делать через JOIN orders. Но это решает только часть задачи:) а как вот их перемешивать?)

    Добавлено спустя 59 минут 18 секунд:
    Код (Text):
    1. SELECT
    2.  `products`.`id`,
    3.  `products`.`title`,
    4.  `products`.`description`,
    5.  `products`.`detecreate`,
    6.   *произ.число* AS `ord`,
    7. FROM `products`
    8. LEFT JOIN `orders`
    9.  ON (`orders`.`products_id` = `products`.`id`)
    10. WHERE `products`.`datecreate` IS NOT NULL
    11. ORDER BY  `orders`.`paid` DESC, RAND(ord) ASC LIMIT 20 OFFSET 0 (1)
    Получилась вот такая петрушка - просто оказалось... Но не понимаю как выполнить вот это:
    ... и оплачены менее месяца назад (т.е. CURRENT() < ADDDATE(orders.datecreate, INTERVAL 1 MONTH) ) ...
     
  4. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Ну куча условий это нормально

    потыкайся. Поймаешь вариант и понимание придет.
     
  5. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Код (Text):
    1. SELECT
    2.  `products`.`id`,
    3.  `products`.`title`,
    4.  `products`.`description`,
    5.  `products`.`detecreate`,
    6.   *произ.число* AS `ord`,
    7. FROM `products`
    8. LEFT JOIN `orders`
    9.  ON (`orders`.`products_id` = `products`.`id`)
    10. WHERE `products`.`datecreate` IS NOT NULL
    11.      AND CURRENT() < ADDDATE(`orders.datecreate`, INTERVAL 1 MONTH) )
    12. ORDER BY  `orders`.`paid` DESC, RAND(ord) ASC LIMIT 20 OFFSET 0 (1)
    Если сделать так, то он выводит только те продукты у которых в ордере дата создания + 1 месяц > текущего времени, что вообще не нужно...
    Может кто еще идей подкинет...
     
  6. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ну ты сам написал такое условие =)

    Добавлено спустя 37 секунд:
    AND CURRENT() < ADDDATE(`orders.datecreate`, INTERVAL 1 MONTH)
    =
    текущего времени < дата создания + 1 месяц
     
  7. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Данный запрос выведет только те записи, в которых выполняется данное условие (AND CURRENT() < ADDDATE(`orders.datecreate`, INTERVAL 1 MONTH) ), а остальные продукты просто проигнорирует :) Уже проверил работу это запроса:) А мне нужно, что продукты удовлетворяющие этому условию были первыми в выдаче среди остальных)
     
  8. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ну так не пиши это условие, раз тебе оно не нужно

    =)
    чувак. ты чего хочешь-то?

    Добавлено спустя 19 секунд:
    UNION и два запроса.
     
  9. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Ежкин кот:) Это выход:) Щас попробую:) Благодарствую!:)
     
  10. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Тестил, пробовал... два запроса по одиночке произвольно сортируются, но когда делаем UNION - все, каюк, никакой рамдомности в SELECT'aх нет :(
    Код (Text):
    1.  
    2. (SELECT
    3.  `products`.`id`,
    4.  `products`.`title`,
    5.  `products`.`description`,
    6.  `products`.`detecreate`,
    7.   *произ.число* AS `ord`,
    8. FROM `products`
    9. LEFT JOIN `orders`
    10.  ON (`orders`.`products_id` = `products`.`id`)
    11. WHERE `products`.`datecreate` IS NOT NULL
    12.      AND CURRENT() < ADDDATE(`orders.datecreate`, INTERVAL 1 MONTH) )
    13. [b]ORDER BY  RAND(ord) ASC [/b]) - это не срабатывает при юнион
    Такой вот запрос:
    Код (Text):
    1.  
    2. (SELECT
    3.  `products`.`id`,
    4.  `products`.`title`,
    5.  `products`.`description`,
    6.  `products`.`detecreate`,
    7.   *произ.число* AS `ord`,
    8. FROM `products`
    9. LEFT JOIN `orders`
    10.  ON (`orders`.`products_id` = `products`.`id`)
    11. WHERE `products`.`datecreate` IS NOT NULL
    12.      AND CURRENT() < ADDDATE(`orders.datecreate`, INTERVAL 1 MONTH) )
    13.      AND `orders`.`paid` = 1
    14. ORDER BY  RAND(ord) ASC )
    15.  
    16. UNION
    17.  
    18. (SELECT
    19.  `products`.`id`,
    20.  `products`.`title`,
    21.  `products`.`description`,
    22.  `products`.`detecreate`,
    23.   *произ.число* AS `ord`,
    24. FROM `products`
    25. WHERE `products`.`datecreate` IS NOT NULL
    26. ORDER BY  RAND(ord) ASC )
    при изменении произвольного числа, по идее должны перемешиваться строки, но этого не происходит :(

    так же добавлял ORDER BY RAND(ord) ASC
    Код (Text):
    1. ( SELECT ... ) union (SELECT ) ORDER BY  RAND(ord) ASC
    все равно нуль реакции
     
  11. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    =( я нижнаю
     
  12. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Перерыл гуглю яндексом и ничего... Как я понимаю в UNION по "псевдополю" в низя походу сделать ORDER BY...
     
  13. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Сделал вот как:

    Код (Text):
    1. SELECT  * , 234123 as `ord`
    2. FROM
    3. (
    4.   (
    5.     SELECT *
    6.     FROM products
    7.     LEFT JOIN `orders`
    8.      ...
    9.   )
    10.  
    11.   UNION
    12.  
    13.   (
    14.     SELECT *
    15.     FROM products
    16.     LEFT OUTER JOIN `orders`
    17.     ....
    18.   )
    19.    
    20. )
    21. ORDER BY RAND('ord)
    При данном запросе задача решается частично, т.е. позиции не перемешивается в SELECT, который идет в перед UNION
     
  14. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Жуть. Это прям матрёшка. Как скорость?
     
  15. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Еще какая матрешка... Ну как сказать скорость:), что то нужно придумать по-правильнее... не быстро... при моих данных, а это 1/10 от реальной, по phpmyadmin запрос примерно 0.008 - 0.01 .. Пока как лучше придумать я хз...
     
  16. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Подскажите с запросом пожалуйста :)
    Нужно выбрать из первой (products) все, кроме тех, что во второй (orders) имеют `orders`.`paid` = 0 и CURENT() вне периода `orders`.`datecreate` + 1 месяц , а ну и соответственно именно эти и не брать `products`.`id` = `orders`.`products_id` )
     
  17. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    =( походу надо когонить привлекать в топик
     
  18. nickstop

    nickstop Новичок

    С нами с:
    14 май 2014
    Сообщения:
    11
    Симпатии:
    0
    Код (Text):
    1. SELECT * FROM products p WHERE p.id NOT IN (SELECT products_id FROM orders o WHERE o.paid=0 AND (CURDATE() < o.datacreate OR CURDATE() > DATE_ADD(o.datacreate, INTERVAL +1 MONTH)))
    Решение простое, как две копейки! :) Благодарен, человеку, кто подсказал:)

    К моей матрешки прибавился еще запросик:) Походу вешайся сервер! :)