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

Форум MySQL

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

 

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

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

тема: Сортировка
 
 автор: serenya1983   (27.11.2012 в 16:55)   письмо автору
 
 

Есть таблица:
id - INT Primary = 1,2,3,4,5,6,7,8
level - INT = 2,4,5,6,8,10,15,16

Есть число например N = 8 не имеющие отношение к таблице;
нужно выбрать все значения и отсортировать по level в порядке от N (N как начало сортировки) (используя только SQL запрос)
ИТОГ который должен получиться:
level = 8, 6,10, 5,15,4,16,2 (т.е. от N берём значения по бокам слева-справа, слева-справа)
Спасибо.

  Ответить  
 
 автор: Valick   (27.11.2012 в 17:20)   письмо автору
 
   для: serenya1983   (27.11.2012 в 16:55)
 

это какая-то учебная задача? или у кого-то не в порядке с логикой?

  Ответить  
 
 автор: serenya1983   (27.11.2012 в 19:55)   письмо автору
 
   для: Valick   (27.11.2012 в 17:20)
 

это задача которая нужна для подбора уровня который был бы равен текущему или расходился бы от него сначало в 1 потом в 2 и т.д. Т.е. если текущий = 8, то сначало надо попробывать найти с таким же т.е.=8. если с таким же нет то попробывать подобрать с 7, если с 7 нет то с 9, если с 9 нет то с 6, нет с 6 то с 10 и т.д.
Понятно что можно сделать php, вопрос можно ли с помощью SQL запроса так выбрать.

  Ответить  
 
 автор: Valick   (27.11.2012 в 20:49)   письмо автору
 
   для: serenya1983   (27.11.2012 в 19:55)
 

что значит попробовать? вам просто нужно выбрать ближайшие существующие по обе стороны и определить кто из них ближе.
ответ на ваш вопрос - можно :) запрос на определение ближайших здесь на форуме неоднократно всплывал, а при помощи конструкции IF можно сравнить выбранные величины вычитая из них по модулю искомое число.
Если сами не осилите постараюсь завтра написать сам запрос, сейчас времени нет, на БГ идти надо :)
Но запрос получится трехэтажным, зачем это делать именно одним запросом? Двумя запросами тут оптимальнее, да и то если первый запрос "в молоко", а то и до второго сложного запроса может и не дойдет дело.

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 00:51)   письмо автору
 
   для: Valick   (27.11.2012 в 20:49)
 

> Но запрос получится трехэтажным
;-)

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 01:00)   письмо автору
 
   для: Valick   (27.11.2012 в 17:20)
 

Думаю такая выборка где-нибудь в статистике очень даже уместна.... Для построения какого-нибудь графика отклонений от медианы или еще какой-нить фигни.

  Ответить  
 
 автор: Valick   (28.11.2012 в 01:40)   письмо автору
 
   для: Sfinks   (28.11.2012 в 01:00)
 

может быть, а может быть и нет :)

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 00:48)   письмо автору
 
   для: serenya1983   (27.11.2012 в 16:55)
 

Прикольная задачка =) Решается математически-логически =)
SELECT level
FROM tbl
CROSS JOIN (SELECT 8 x)x
ORDER BY abs(x-level), sign(level-x)

  Ответить  
 
 автор: Valick   (28.11.2012 в 01:39)   письмо автору
 
   для: Sfinks   (28.11.2012 в 00:48)
 

завтра конечно проверю, но вот в чем проблема, если в таблице полтора миллиона записей зачем тащить их все когда нужно максимум три? ;)

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 02:48)   письмо автору
 
   для: Valick   (28.11.2012 в 01:39)
 

Затем что эти 3 вы будете выбирать с 3мя сортировками (опять же всей таблицы) и union'ом -это если "одним" запросом, либо 2мя сортировками и 2мя обращениями к серваку.
А к моему допишите LIMIT 3 и получите 1 сортировку, 1 обращение и те же 3 строки.
Это если нужно только 3.
А если график? Я в 1ом посте ничего про 3 строки не видел.

Ну как там БГ? =)

  Ответить  
 
 автор: Valick   (28.11.2012 в 09:22)   письмо автору
 
   для: Sfinks   (28.11.2012 в 02:48)
 

БГ (battleground, не путать с Борисом Гребенщековым) нормально, но кап ОЗ еще на прошлой неделе получил, поэтому победа радует не так сильно как хотелось бы :)
По поводу запроса была мысль проверить с разными интервалами, но как смотрю уже и без меня проверили

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 09:35)   письмо автору
 
   для: Valick   (28.11.2012 в 09:22)
 

Ааа... Я-то думал на концерт....

  Ответить  
 
 автор: Igorek   (28.11.2012 в 08:19)   письмо автору
 
   для: Sfinks   (28.11.2012 в 00:48)
 

Круто, только от ожидаемого результата отличается)
> ИТОГ который должен получиться:
> level = 8, 6,10, 5,15,4,16,2

Такой бы код подошел, если бы значения соседних level отличались на константу

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 08:40)   письмо автору
 
   для: Igorek   (28.11.2012 в 08:19)
 

Хм... Вы правы! Не заметил.
Тогда, да - решить можно, но запрос будет трехэтажным. А то и 4х.

  Ответить  
 
 автор: Sfinks   (28.11.2012 в 09:03)   письмо автору
 
   для: Igorek   (28.11.2012 в 08:19)
 

/*<?*/
SELECT level, @n:=if( s=@p, @n+1), @p:=s
FROM
SELECT level
           
abs(x-cast(level as signed))a
           
, case when level=x then 0
                  when level
<x then 1
                  
else 2 end s
      FROM sorting 
      CROSS JOIN 
(SELECT 8 x)x
      ORDER BY 3
,2
)t
CROSS JOIN 
(SELECT @n:=0)n
CROSS JOIN 
(SELECT @p:=0)p
ORDER BY 2
,3
Как-то так....
Но тут уж я не берусь спорить о скорости. Смотря что в реальности нужно.

  Ответить  
 
 автор: Valick   (28.11.2012 в 09:25)   письмо автору
 
   для: Sfinks   (28.11.2012 в 09:03)
 

я сразу ТС сказал, что оптимальнее тут обойтись двумя запросами, жду обоснованного ответа почему именно один нужен.
1
SELECT * FROM table WHERE level =8

2
SELECT IF(
     (ABS(@a:=(SELECT level FROM table WHERE level<8 ORDER BY DESC level LIMIT 1)-8))<
     (ABS(@b:=(SELECT level FROM table WHERE level>8 ORDER BY ASC level LIMIT 1)-8)), @a,@b)

запрос естественно не проверял, может и не рабочий, но при такой постановке задачи я бы работал именно в этом направлении

  Ответить  
 
 автор: serenya1983   (28.11.2012 в 13:10)   письмо автору
 
   для: Valick   (28.11.2012 в 09:25)
 

Всем спасибо, получился один запрос, предварительно установив диапозон выборки по level через php. Получилось примерно это:

$level = 8;
$levels = array();
$levels[] = $level;
for ($i=1;$i<5;$i++) {
    $levels[] = $level+$i;
    if ($level-$i>0) $levels[] = $level-$i;
}
$level_str = implode(",",$levels);

$query = "SELECT level
            FROM `users` 
            WHERE level IN ({$level_str}) 
            ORDER  BY Field(level, {$level_str})
            LIMIT 100"

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

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