|
|
|
| Есть таблица:
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 берём значения по бокам слева-справа, слева-справа)
Спасибо. | |
|
|
|
|
|
|
|
для: serenya1983
(27.11.2012 в 16:55)
| | это какая-то учебная задача? или у кого-то не в порядке с логикой? | |
|
|
|
|
|
|
|
для: Valick
(27.11.2012 в 17:20)
| | это задача которая нужна для подбора уровня который был бы равен текущему или расходился бы от него сначало в 1 потом в 2 и т.д. Т.е. если текущий = 8, то сначало надо попробывать найти с таким же т.е.=8. если с таким же нет то попробывать подобрать с 7, если с 7 нет то с 9, если с 9 нет то с 6, нет с 6 то с 10 и т.д.
Понятно что можно сделать php, вопрос можно ли с помощью SQL запроса так выбрать. | |
|
|
|
|
|
|
|
для: serenya1983
(27.11.2012 в 19:55)
| | что значит попробовать? вам просто нужно выбрать ближайшие существующие по обе стороны и определить кто из них ближе.
ответ на ваш вопрос - можно :) запрос на определение ближайших здесь на форуме неоднократно всплывал, а при помощи конструкции IF можно сравнить выбранные величины вычитая из них по модулю искомое число.
Если сами не осилите постараюсь завтра написать сам запрос, сейчас времени нет, на БГ идти надо :)
Но запрос получится трехэтажным, зачем это делать именно одним запросом? Двумя запросами тут оптимальнее, да и то если первый запрос "в молоко", а то и до второго сложного запроса может и не дойдет дело. | |
|
|
|
|
|
|
|
для: Valick
(27.11.2012 в 20:49)
| | > Но запрос получится трехэтажным
;-) | |
|
|
|
|
|
|
|
для: Valick
(27.11.2012 в 17:20)
| | Думаю такая выборка где-нибудь в статистике очень даже уместна.... Для построения какого-нибудь графика отклонений от медианы или еще какой-нить фигни. | |
|
|
|
|
|
|
|
для: Sfinks
(28.11.2012 в 01:00)
| | может быть, а может быть и нет :) | |
|
|
|
|
|
|
|
для: serenya1983
(27.11.2012 в 16:55)
| | Прикольная задачка =) Решается математически-логически =)
SELECT level
FROM tbl
CROSS JOIN (SELECT 8 x)x
ORDER BY abs(x-level), sign(level-x)
|
| |
|
|
|
|
|
|
|
для: Sfinks
(28.11.2012 в 00:48)
| | завтра конечно проверю, но вот в чем проблема, если в таблице полтора миллиона записей зачем тащить их все когда нужно максимум три? ;) | |
|
|
|
|
|
|
|
для: Valick
(28.11.2012 в 01:39)
| | Затем что эти 3 вы будете выбирать с 3мя сортировками (опять же всей таблицы) и union'ом -это если "одним" запросом, либо 2мя сортировками и 2мя обращениями к серваку.
А к моему допишите LIMIT 3 и получите 1 сортировку, 1 обращение и те же 3 строки.
Это если нужно только 3.
А если график? Я в 1ом посте ничего про 3 строки не видел.
Ну как там БГ? =) | |
|
|
|
|
|
|
|
для: Sfinks
(28.11.2012 в 02:48)
| | БГ (battleground, не путать с Борисом Гребенщековым) нормально, но кап ОЗ еще на прошлой неделе получил, поэтому победа радует не так сильно как хотелось бы :)
По поводу запроса была мысль проверить с разными интервалами, но как смотрю уже и без меня проверили | |
|
|
|
|
|
|
|
для: Valick
(28.11.2012 в 09:22)
| | Ааа... Я-то думал на концерт.... | |
|
|
|
|
|
|
|
для: Sfinks
(28.11.2012 в 00:48)
| | Круто, только от ожидаемого результата отличается)
> ИТОГ который должен получиться:
> level = 8, 6,10, 5,15,4,16,2
Такой бы код подошел, если бы значения соседних level отличались на константу | |
|
|
|
|
|
|
|
для: Igorek
(28.11.2012 в 08:19)
| | Хм... Вы правы! Не заметил.
Тогда, да - решить можно, но запрос будет трехэтажным. А то и 4х. | |
|
|
|
|
|
|
|
для: Igorek
(28.11.2012 в 08:19)
| |
/*<?*/
SELECT level, @n:=if( s=@p, @n+1, 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
| Как-то так....
Но тут уж я не берусь спорить о скорости. Смотря что в реальности нужно. | |
|
|
|
|
|
|
|
для: 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)
|
запрос естественно не проверял, может и не рабочий, но при такой постановке задачи я бы работал именно в этом направлении | |
|
|
|
|
|
|
|
для: 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"
|
| |
|
|
|