За последние 24 часа нас посетили 18874 программиста и 1616 роботов. Сейчас ищут 920 программистов ...

Своеобразная выборка из бд

Тема в разделе "MySQL", создана пользователем kazrem, 19 мар 2013.

  1. kazrem

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

    С нами с:
    19 мар 2013
    Сообщения:
    18
    Симпатии:
    1
    Честно говоря, не понял строчку "если ответ меньше чем 4 содержит, делаешь запрос с конца/начала" ))
     
  2. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    а какое слово ты не понял? =) разбери её как алгоритм по словам отдельно.

    если ты ищешь 4 строки, которые больше чем твой id то:
    если ответ от базы данных содержит меньше чем четыре строки, то
    надо сделать запрос с начала таблицы, ибо очевидно, что в сторону конца таблицы таких не нашлось.
     
  3. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.251
    Адрес:
    там-сям
    У меня есть SQL-запрос, которым можно получить нужные данные за один прием. Причем "дырки" в нумерации ему не страшны. Но я пока не буду публиковать, чтобы не нарушать интригу ;)
    UNION, ORDER и LIMIT
    Топикстартер, попытайся сам.
     
  4. kazrem

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

    С нами с:
    19 мар 2013
    Сообщения:
    18
    Симпатии:
    1
    От интриги уже ничего не осталось, выкладывайте уже! ))

    Добавлено спустя 11 минут 36 секунд:
    вот в union я не силен, так что ни за что не догадаюсь. Так что, уважаемый artoodetoo, ждем вашей публикации.
     
  5. kazrem

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

    С нами с:
    19 мар 2013
    Сообщения:
    18
    Симпатии:
    1
    В общем после долгих чесаний репы придумал такое
    Код (Text):
    1. $sql = "SELECT * FROM `table` where `cat`='$cat' and `id`<".$_REQUEST['id']." ORDER BY `id` DESC LIMIT 4";
    2. $rs = mysql_query($sql) or die(mysql_error());
    3. if(mysql_num_rows($rs) >3)
    4. бла-бла-бла
    5. else
    6. {$sql = "SELECT * FROM `table` where `cat`='$cat' and `id`>".$_REQUEST['id']."+4 ORDER BY `id` asc LIMIT 4";
    7. бла-бла-бла
    это предыдущие записи

    Код (Text):
    1. $sql = "SELECT * FROM `table` where `cat`='$cat' and `id`>".$_REQUEST['id']." ORDER BY `id` asc LIMIT 4";
    2. $rs = mysql_query($sql) or die(mysql_error());
    3. if(mysql_num_rows($rs) >3)
    4. бла-бла-бла
    5. else
    6. {$sql = "SELECT * FROM `table` where `cat`='$cat' and `id`<".$_REQUEST['id']."-4 ORDER BY `id` desc LIMIT 4";
    7. бла-бла-бла
    это следующие записи

    Количество id в бд 180
    в этом случае при заходе на text.php?id=2 , показывает такие id: 7, 8, 9, 10, и 3, 4, 5, 6
    при заходе на text.php?id=177 показывает такие id: 176, 175, 174, 173 и 172, 171, 170, 169
    ну и наконец при заходе в середину, например на text.php?id=5 показывает 4, 3, 2, 1 и 6, 7, 8, 9 (идеальный вариант, выводится так, как нужно)

    Вот как-то так. На большее знаний увы не хватило...
     
  6. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.251
    Адрес:
    там-сям
    Ладно, вот моё. Здесь мне пофигу эффективность или удобство использования. Просто упражнение на владение SQL.
    Опять же ради чистой науки отброшу фильтры по "категориям" и чего там ещё. Для задачи это НЕ принципиально абсолютно. Покажу шаг за шагом.

    1. Ввожу свои данные:
    Код (Text):
    1. DROP TABLE IF EXISTS `numbers`;
    2. CREATE TABLE `numbers` (
    3.   `id` int(10) NOT NULL AUTO_INCREMENT,
    4.   `value` varchar(20) NOT NULL DEFAULT'',
    5.   PRIMARY KEY (`id`)
    6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    7.  
    8. INSERT INTO `numbers` VALUES
    9.   ( 1, 'Lorem ipsum'),
    10.   ( 4, 'dolor sit amet'),
    11.   ( 5, 'consectetur'),
    12.   ( 8, 'adipiscing elit'),
    13.   (12, 'Mauris nec nisi'),
    14.   (13, 'leo, at rutrum nulla'),
    15.   (15, 'Sed lectus sem'),
    16.   (17, 'sodales sit amet'),
    17.   (18, 'suscipit quis'),
    18.   (44, 'euismod ut lorem'),
    19.   (50, 'Pellentesque dapibus');
    имеем 11 строк, в нумерации "дырки", чтобы нереально простые решения не проходили ;)
    то есть всего нам надо получить 9 записей, включая "текущую" (если столько наберется в таблице). в примерах буду запрашивать все данные, но для простоты результат вывожу как строку чисел.

    1. Рассмотрим простой запрос "четыре предыдущие и текущая запись", ожидаем получить 5 строк.
    для текущего id=17:
    Код (Text):
    1. SELECT `id`, `value`
    2. FROM `numbers`
    3. WHERE `id`<=17
    4. ORDER BY `id` DESC
    5. LIMIT 5
    -> 17 15 13 12 8
    для id=5
    -> 5 4 1
    не хватает! надо дополнять записями с конца.

    3. появляется UNION:
    Код (Text):
    1. (
    2.   SELECT `id`, `value`
    3.   FROM `numbers`
    4.   WHERE `id`<=5
    5.   ORDER BY `id` DESC
    6.   LIMIT 5
    7. )
    8. UNION
    9. (
    10.   SELECT `id`, `value`
    11.   FROM `numbers`
    12.   ORDER BY `id` DESC
    13.   LIMIT 4
    14. )
    -> 5 4 1 50 44 18 17
    получилось несколько больше, чем надо. Вкладываем всё в ещё один запрос и обрезаем.

    4. Окончательный запрос "четыре предыдущие и текущая В КОЛЬЦЕ"
    Код (Text):
    1. SELECT *
    2. FROM (
    3.   (SELECT `id`, `value` FROM `numbers` WHERE `id`<=5 ORDER BY `id` DESC LIMIT 5)
    4.   UNION
    5.   (SELECT `id`, `value` FROM `numbers` ORDER BY `id` DESC LIMIT 4)
    6. ) AS `prev`
    7. LIMIT 5
    -> 5 4 1 50 44
    bingo! пробуем заменить `id`<=5 на `id`<=17 или `id`<=44 -- работает так, как заказано!

    5. Аналогично составляем запрос "четыре следующие записи В КОЛЬЦЕ" (здесь уже не надо включать текущую)
    Код (Text):
    1. SELECT *
    2. FROM (
    3.   (SELECT `id`, `value` FROM `numbers` WHERE `id`>17 ORDER BY `id` ASC LIMIT 4)
    4.   UNION
    5.   (SELECT `id`, `value` FROM `numbers` ORDER BY `id` ASC LIMIT 4)
    6. ) AS `next`
    7. LIMIT 4
    -> 18 44 50 1

    6. Объединим через новый UNION prev и next, получаем окончательный запрос "четыре предыдущие, текущая и четыре следующие записи В КОЛЬЦЕ":
    Код (Text):
    1. (
    2.   SELECT *
    3.   FROM (
    4.     (SELECT `id`, `value` FROM `numbers` WHERE `id`<=17 ORDER BY `id` DESC LIMIT 5)
    5.     UNION
    6.     (SELECT `id`, `value` FROM `numbers` ORDER BY `id` DESC LIMIT 4)
    7.   ) AS `prev`
    8.   LIMIT 5
    9. )
    10. UNION
    11. (
    12.   SELECT *
    13.   FROM (
    14.     (SELECT `id`, `value` FROM `numbers` WHERE `id`>17 ORDER BY `id` ASC LIMIT 4)
    15.     UNION
    16.     (SELECT `id`, `value` FROM `numbers` ORDER BY `id` ASC LIMIT 4)
    17.   ) AS `next`
    18.   LIMIT 4
    19. )
    -> 17 15 13 12 8 18 44 50 1
    предлагаю в качестве "текущего" испытать также 5 и 44.

    В итоге у нас есть один SQL-запрос, выдающий все нужные строки за один прием. Этот набор упорядочен неочевидным образом, можно обернуть всё в еще один SELECT ... ORDER BY `id`, а можно все остальные манипуляции оставить на долю PHP.

    Да прибудет с вами сила!
     
  7. kazrem

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

    С нами с:
    19 мар 2013
    Сообщения:
    18
    Симпатии:
    1
    Вообще супер!!! Молодца! Даже потерял уже веру что это возможно. Спасибо!
    Пока на webmoney пусто, как что-нибудь появится, обязательно пошлю благодарность.
     
  8. artoodetoo

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

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.251
    Адрес:
    там-сям
    ну дай бог тебе богатства, милчеловек! :D
     
  9. igordata

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

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768