Проблем с MIN() и MAX()

5 отговора 344 прегледа
#1

Проблем с MIN() и MAX()

Привет ...

mySQL 4.0.21

CREATE TABLE `sections` (
`id` int(11) unsigned NOT NULL auto_increment,
`title` varchar(100) NOT NULL default '',
`code` varchar(4) NOT NULL default '',
`descr` varchar(50) NOT NULL default '',
`content` text NOT NULL,
`last_edited` datetime NOT NULL default '0000-00-00 00:00:00',
`disabled` tinyint(1) unsigned NOT NULL default '0',
PRIMARY KEY (`id`)
) TYPE=MyISAM

mysql> select id from sections;
+----+
| id |
+----+
| 3 |
| 7 |
| 8 |
| 9 |
| 12 |
| 13 |
| 14 |
| 15 |
+----+
8 rows in set (0.00 sec)

Проблем:
Как с една заявка да изкарам съществуващите най-близка по-малка и най-близката по-голяма стойност от дадена:
Примерно за 14 трябва да получа 13 и 15, за 9 - 8 и 12 ... постигам нужния ми резултат с :

SELECT MAX(t1.id) AS my_min, MIN(t2.id) AS my_max
FROM sections AS t1 JOIN sections AS t2
WHERE t2.id > 8 AND t1.id < 8

но ако пусна заявката със стойност, която е извън границите на моето id, получавам два null-a :(
С други думи проблема ми е примерно за търсена стойност 3 да получа - 3 и 7, а за 15 - 14 и 15 ...

Тръгнах така, но не получавам, това което ми е нужно, пък и логиката ми нещо съвсем окуця ... :(

SELECT COALESCE(MAX(t1.id),MIN(t3.id)) AS my_min, COALESCE(MIN(t2.id),MAX(t3.id)) AS my_max
FROM sections AS t1
JOIN sections AS t2
JOIN sections AS t3
WHERE t2.id > 3 AND t1.id < 3

Предварително мерси ...

Отговор
в отговор на Cтyдeнт #2

Re: Ама откъде го измъкна това COALESCE???

COALESCE() пък какво общо има в случая?

що не си направиш две отделни заявки с LIMIT 1 и да ги обединиш с UNION?

mysql> SELECT * FROM t;
+----+
| id |
+----+
| 3 |
| 7 |
| 8 |
| 9 |
| 12 |
| 13 |
| 14 |
| 15 |
+----+
8 rows in set (0.00 sec)

mysql> SET @val:=9; (SELECT MAX(id) FROM t WHERE id < @val) UNION (SELECT MIN(id) FROM t WHERE id > @val);
Query OK, 0 rows affected (0.02 sec)

+---------+
| MAX(id) |
+---------+
| 8 |
| 12 |
+---------+
2 rows in set (0.02 sec)

Наистина трябва да си поиграеш в граничните случаи ама не го прави с тая грозотия COALESCE, Използвай IF или направо IFNULL


А за да получиш 2 стойности и в случая когато таблицата има само един ред използвай UNION ALL



salle.online.bg/sig

Редактирано от salle на

Отговор
в отговор на salle #3

Трябват ми двете стоиности в един ред !

Пролемът е, че ми трябват двете стойности в един ред ... с UNION ми е ясно, че мога да ги получа ... няма ли вариант за някакво обединение ?

Отговор
в отговор на Cтyдeнт #4

Re: А каква е разликата?

Каква е разликата дали имаш


+-----+-----+
| min | max |
+-----+-----+
| 3 | 5 |
+-----+-----+

+---------+
| min_max |
+---------+
| 3 |
| 5 |
+---------+

salle.online.bg/sig
Отговор
в отговор на salle #5

Голяма ...

В единия вариант имаш достъп веднага ... няма нужда от итерации ... а в другия трябва да се цикли ...

Отговор
в отговор на Cтyдeнт #6

Re: Голяма ...

От MySQL не разбирам (дали поддържа субселекти), на Оракъл може нещо такова да се направи:

select
( select
Max(value)
from
MY_TABLE
where
(value < neshtoto_koeto_e_granicata_okolo_koiato_se_vyrtim)
) as LOWER_NEAREST_VALUE,
( select
Min(value)
from
MY_TABLE
where
(value > neshtoto_koeto_e_granicata_okolo_koiato_se_vyrtim)
) as UPPER_NEAREST_VALUE
from
DUAL


Ама си мисля, че и да имаш 1-2 реда повече код за да обработиш Result set от 2 записа е все тая.

Edit: Ако neshtoto_koeto_e_granicata_okolo_koiato_se_vyrtim е най-голямата и/или най-малката стойност в таблицата можеш да си облечеш субселектите с Nvl (еквивалента в МъСЯЛ (:-))) - Nvl( (select ..... from .....) , neshtoto_koeto_e_granicata_okolo_koiato_se_vyrtim)

Егати пауъра

Редактирано от timmyyy на

Отговор