id | number | message
0 | 0 | ghbgbghgh
1 | 1 | йцуйцуйу
2 | 2 | енгенгег
4 | 4 | фывфыв
6 | 6 | митмитмит
7 | 3 | dfvbdvdfvfd
9 | 7 | hhdgfhbgdfg
10 | 8 | 3456g653vv6
Как вывести из столбца number наименьшее целое положительное число, которого ещё нет в этом столбце. В данном примере это 5.
Спустя 3 минуты, 9 секунд (24.03.2011 - 19:30) neadekvat написал(а):
Приведите нормальный дамп в виде sql-кода - вручную вбивать ваши данные не комильфо, как и показывать запрос, не проверив его.
Спустя 2 минуты, 22 секунды (24.03.2011 - 19:32) Trianon написал(а):
dzisay
почему пять?
Нуля, к примеру, тоже нет.
почему пять?
Нуля, к примеру, тоже нет.
Спустя 4 минуты, 25 секунд (24.03.2011 - 19:37) dzisay написал(а):
neadekvat К сожалению база пока ещё только в проекте, поэтому расписал как смог.
Trianon Вы правы сейчас подправлю.
Trianon Вы правы сейчас подправлю.
Спустя 2 минуты, 18 секунд (24.03.2011 - 19:39) Trianon написал(а):
dzisay
Так ведь и -7 нету.
Эдак Вы долго будете подправлять.
Так ведь и -7 нету.

Эдак Вы долго будете подправлять.
Спустя 2 минуты, 22 секунды (24.03.2011 - 19:41) sergeiss написал(а):
dzisay - а я так спрошу: свои-то какие соображения есть по этому поводу?
Спустя 12 минут, 36 секунд (24.03.2011 - 19:54) dzisay написал(а):
Trianon
Подправил в описании вопроса.
sergeiss
Думаю что нужно конструировать цикл до появления нужного значения...только вот как именно
Подправил в описании вопроса.
sergeiss
Думаю что нужно конструировать цикл до появления нужного значения...только вот как именно

Спустя 12 минут, 42 секунды (24.03.2011 - 20:07) neadekvat написал(а):
Но ноль не является положительным числом :)
Ну, ладно.. если с перебором, с помощью php, то как-то так:
Если 0 все-таки может быть в ряду чисел, то $prev_number = -1; в начале.
На чистом sql я бы интереса ради, может, и посидел, но раз вы не хотите давать нормальный дамп, то и желания такого не возникает.
Ну, ладно.. если с перебором, с помощью php, то как-то так:
$query = mysql_query("SELECT * FROM tbl ORDER BY number ASC");
$prev_number = 0;
while($arr = mysql_fetch_assoc($query))
{
if (($arr['number'] - $prev_number) != 1) {
echo ++$prev_number; // искомое число
break;
}
$prev_number = $arr['number'];
}
Если 0 все-таки может быть в ряду чисел, то $prev_number = -1; в начале.
На чистом sql я бы интереса ради, может, и посидел, но раз вы не хотите давать нормальный дамп, то и желания такого не возникает.
Спустя 2 минуты, 36 секунд (24.03.2011 - 20:09) sergeiss написал(а):
Цитата (neadekvat @ 24.03.2011 - 21:07) |
но раз вы не хотите давать нормальный дамп... |
...такой "дамп" самому нарисовать - на 3 минуты работы, да еще и перекур сделать успеть можно

Спустя 2 минуты, 40 секунд (24.03.2011 - 20:12) neadekvat написал(а):
Цитата (sergeiss @ 24.03.2011 - 20:09) |
...такой "дамп" самому нарисовать - на 3 минуты работы, да еще и перекур сделать успеть можно |
Внимательно посмотрите подпись под моей аватаркой

Спустя 5 минут, 20 секунд (24.03.2011 - 20:17) dzisay написал(а):
-- phpMyAdmin SQL Dump
-- version 3.2.3
-- http://www.phpmyadmin.net
--
-- Хост: localhost
-- Время создания: Мар 24 2011 г., 22:17
-- Версия сервера: 5.1.40
-- Версия PHP: 5.3.3
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- База данных: `izlej`
--
-- --------------------------------------------------------
--
-- Структура таблицы `all`
--
CREATE TABLE IF NOT EXISTS `all` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`number` int(5) NOT NULL,
`message` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=9 ;
--
-- Дамп данных таблицы `all`
--
INSERT INTO `all` (`id`, `number`, `message`) VALUES
(1, 1, 'прорппртртрптпрт'),
(2, 2, 'паипаививпиапиа'),
(3, 4, 'паывпавпывапав'),
(4, 6, 'выфвмывмфымфывм'),
(5, 3, 'пвыапавыпвапва'),
(6, 7, 'апаывпывапыавп'),
(7, 8, 'апыавпвапывпывп'),
(8, 9, 'авымваывамывамывам');
-- version 3.2.3
-- http://www.phpmyadmin.net
--
-- Хост: localhost
-- Время создания: Мар 24 2011 г., 22:17
-- Версия сервера: 5.1.40
-- Версия PHP: 5.3.3
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
--
-- База данных: `izlej`
--
-- --------------------------------------------------------
--
-- Структура таблицы `all`
--
CREATE TABLE IF NOT EXISTS `all` (
`id` int(5) NOT NULL AUTO_INCREMENT,
`number` int(5) NOT NULL,
`message` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=9 ;
--
-- Дамп данных таблицы `all`
--
INSERT INTO `all` (`id`, `number`, `message`) VALUES
(1, 1, 'прорппртртрптпрт'),
(2, 2, 'паипаививпиапиа'),
(3, 4, 'паывпавпывапав'),
(4, 6, 'выфвмывмфымфывм'),
(5, 3, 'пвыапавыпвапва'),
(6, 7, 'апаывпывапыавп'),
(7, 8, 'апыавпвапывпывп'),
(8, 9, 'авымваывамывамывам');
Спустя 12 минут, 57 секунд (24.03.2011 - 20:30) dzisay написал(а):
neadekvat Выдаёт ошибку в строке "while($arr = mysql_fetch_assoc($query))"
Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in Z:\home\izlej.ru\www\add\result.php on line 52
Warning: mysql_fetch_assoc() expects parameter 1 to be resource, boolean given in Z:\home\izlej.ru\www\add\result.php on line 52
Спустя 2 минуты, 1 секунда (24.03.2011 - 20:32) neadekvat написал(а):
dzisay, вы свои данные хоть подставили в запрос?
Возьмите имя таблицы и столбца в ``
Плюс, мой код сработает, если значения number не могут повторяться
Возьмите имя таблицы и столбца в ``
Плюс, мой код сработает, если значения number не могут повторяться
Спустя 3 минуты, 41 секунда (24.03.2011 - 20:36) dzisay написал(а):
$db = mysql_connect("localhost", "user", "pass12345");
mysql_select_db("izlej", $db);
$query = mysql_query("SELECT * FROM all ORDER BY number ASC");
$prev_number = 0;
while($arr = mysql_fetch_assoc($query))
{
if (($arr['number'] - $prev_number) != 1) {
echo ++$prev_number; // искомое число
break;
}
$prev_number = $arr['number'];
}
mysql_select_db("izlej", $db);
$query = mysql_query("SELECT * FROM all ORDER BY number ASC");
$prev_number = 0;
while($arr = mysql_fetch_assoc($query))
{
if (($arr['number'] - $prev_number) != 1) {
echo ++$prev_number; // искомое число
break;
}
$prev_number = $arr['number'];
}
Спустя 23 секунды (24.03.2011 - 20:36) neadekvat написал(а):
Цитата (neadekvat @ 24.03.2011 - 20:32) |
Возьмите имя таблицы и столбца в `` Плюс, мой код сработает, если значения number не могут повторяться |
Спустя 4 минуты, 34 секунды (24.03.2011 - 20:41) dzisay написал(а):

Спустя 13 минут, 49 секунд (24.03.2011 - 20:55) neadekvat написал(а):
Там без пол-литра хранимых походу не обойтись. Хотя, быть может, я усложняю. Но на "простом" sql не вижу решение.
Спустя 4 минуты, 39 секунд (24.03.2011 - 20:59) dzisay написал(а):
Ну ладно и на этом огромное спасибо

Спустя 1 час, 39 минут, 13 секунд (24.03.2011 - 22:38) sergeiss написал(а):
Цитата (neadekvat @ 24.03.2011 - 21:55) |
Но на "простом" sql не вижу решение. |
Оно есть... Я только вспомню, как делал, и напишу.
Спустя 4 минуты, 33 секунды (24.03.2011 - 22:43) neadekvat написал(а):
Цитата (sergeiss @ 24.03.2011 - 22:38) |
Оно есть... Я только вспомню, как делал, и напишу. |
Я не отрицал этого

Хотя, я, возможно, все-таки
Цитата (neadekvat @ 24.03.2011 - 20:55) |
усложняю |
и решение где-то здесь, совсем рядом.
Спустя 48 минут, 26 секунд (24.03.2011 - 23:31) Trianon написал(а):
SELECT
MIN(p.number+1) AS hole
FROM tab p
LEFT JOIN tab q ON q.number = p.number+1
WHERE q.number IS NULL
Спустя 25 минут, 36 секунд (24.03.2011 - 23:57) neadekvat написал(а):
А ведь думал, что что-то на NULL завязанное будет 
Правда, Дмитрий, поясни, пожалуйста, почему q.number равняется p.number+1, и при этом является NULL?

Правда, Дмитрий, поясни, пожалуйста, почему q.number равняется p.number+1, и при этом является NULL?
Спустя 8 часов, 52 минуты, 41 секунда (25.03.2011 - 08:50) Trianon написал(а):
Табличное выражение tab p LEFT JOIN tab q ON q.number = p.number+1
без WHERE:
Выжимка из того же выражения после фильтрации по WHERE q.number IS NULL :
Значение выражения p.number+1 для полученных строк :
Результат агрегатной функции MIN(p.number+1) :
без WHERE:
p q
1 2
2 3
4 NULL
6 7
3 4
7 8
8 9
9 NULL
Выжимка из того же выражения после фильтрации по WHERE q.number IS NULL :
p q
4 NULL
9 NULL
Значение выражения p.number+1 для полученных строк :
5
10
Результат агрегатной функции MIN(p.number+1) :
5
Спустя 30 минут, 34 секунды (25.03.2011 - 09:20) kirik написал(а):
Боюсь что товарищ dzisay изобретает (точнее просит помощи в изобретении) механизм, который будет заполнять пропуски в поле id, которое должно быть автоинкриментным. Если это так, то вы, dzisay, встали не на ту дорожку, которая ведёт на тёмную сторону силы..
Спустя 49 минут, 22 секунды (25.03.2011 - 10:10) Trianon написал(а):
автоинкрементный первичный ключ id у товарища уже есть.
А значения в столбиках идентичны не для всех строк.
Это я к тому, что формально товарищ из-под такого обвинения выползет не запачкавшись.
А если он таким образом решил нас запутать, то это очень хитрый товарищ
Лично я склонен предположить, что он, распределяя некий дискретный ресурс с приоритетом в начале диапазона (места в зале кинотеатра, часы регистрации брака в ЗАГСе, и т.п.) , отыскивает дырки свободных слотов .
А значения в столбиках идентичны не для всех строк.
Это я к тому, что формально товарищ из-под такого обвинения выползет не запачкавшись.
А если он таким образом решил нас запутать, то это очень хитрый товарищ

Лично я склонен предположить, что он, распределяя некий дискретный ресурс с приоритетом в начале диапазона (места в зале кинотеатра, часы регистрации брака в ЗАГСе, и т.п.) , отыскивает дырки свободных слотов .
Спустя 21 минута, 44 секунды (25.03.2011 - 10:31) neadekvat написал(а):
Trianon, ух ты
Спасибо.

Спустя 1 минута, 20 секунд (25.03.2011 - 10:33) kirik написал(а):
Trianon
Глаза продрал, извиняюсь за грязные обвинения
Прочитал что нужно для поля id искать пропуски..
Глаза продрал, извиняюсь за грязные обвинения

Спустя 4 часа, 20 минут, 30 секунд (25.03.2011 - 14:53) dzisay написал(а):
Цитата (Trianon @ 25.03.2011 - 07:10) |
это очень хитрый товарищ ![]() |
Ну здесь вы переборщили, я всего лишь новичок

Спустя 10 минут, 33 секунды (25.03.2011 - 15:04) dzisay написал(а):
А конструкция сия мне нужна для последующего рандомного вывода строки, придав ей уже конкретное значение:
При таком подходе пробелы в number не позволительны.
То есть я решил, что лучше напрягать сервер при вводе этих данных, нежели при выводе. Так как первое ожидается во много раз реже чем второе.
kirikНа правильном ли я пути? :unsure:
$query = mysql_query("SELECT `id` FROM `table`")
$amount = mysql_num_rows($query);
$total = mt_rand(1, $amount);
При таком подходе пробелы в number не позволительны.
То есть я решил, что лучше напрягать сервер при вводе этих данных, нежели при выводе. Так как первое ожидается во много раз реже чем второе.
kirikНа правильном ли я пути? :unsure:
Спустя 7 минут (25.03.2011 - 15:11) sergeiss написал(а):
Цитата (dzisay @ 25.03.2011 - 16:04) |
На правильном ли я пути? |
На совершенно неправильном пути...
Потому что если тебе надо получить одно произвольное значение из таблицы, то это делается намного проще. Примерно так:
select * from table order by rand() limit 1
Спустя 2 часа, 25 минут, 12 секунд (25.03.2011 - 17:36) dzisay написал(а):
sergeiss
А если строк будет 1000, 2000, 3000? Слышал, что это довольно ресурсоемкое решение.
А если строк будет 1000, 2000, 3000? Слышал, что это довольно ресурсоемкое решение.
Спустя 45 минут, 12 секунд (25.03.2011 - 18:21) Trianon написал(а):
Допустим,
а) Вы это поле держите только и исключительно для мгновенных обращений к случайной строке через ключ уникального индекса.
б) Проблемы возникают из-за того, что при удалении записей поле теряет непрерывность.
некоторая сермяга в этом есть...
Но ведь удаляя запись, можно сразу восстановить непрерывность поля, обменяв значения поля для двух записей - удаляемой и последней.
Тогда впоследствии не придется искать дыры.
а) Вы это поле держите только и исключительно для мгновенных обращений к случайной строке через ключ уникального индекса.
б) Проблемы возникают из-за того, что при удалении записей поле теряет непрерывность.
некоторая сермяга в этом есть...
Но ведь удаляя запись, можно сразу восстановить непрерывность поля, обменяв значения поля для двух записей - удаляемой и последней.
Тогда впоследствии не придется искать дыры.
Спустя 1 час, 42 минуты, 59 секунд (25.03.2011 - 20:04) sergeiss написал(а):
Цитата (dzisay @ 25.03.2011 - 18:36) |
А если строк будет 1000, 2000, 3000? Слышал, что это довольно ресурсоемкое решение. |
А ты думаешь, что предложенный тебе ранее вариант будет выполняться мгновенно?

Если уж тебе очень хочется сделать в ПХП, то тогда всё равно не надо "восстанавливать непрерывность". Просто запиши полученные id в массив и выбери оттуда произвольное число. Только время замерь... Очень может быть, что внутри SQL быстрее получится.
Спустя 9 минут, 15 секунд (25.03.2011 - 20:13) dzisay написал(а):
Цитата (sergeiss @ 25.03.2011 - 17:04) |
А ты думаешь, что предложенный тебе ранее вариант будет выполняться мгновенно? ![]() |
Не спорю, что создание строк будет массивным.
Я же борюсь за мгновенность и простоту вывода строк

Спустя 9 часов, 51 минута, 53 секунды (26.03.2011 - 06:05) kirik написал(а):
dzisay
Рандом - зло :)
Я делал примерно так (зная допустим что у меня уже в таблице 1000 записей или немногим больше):
где `id` - инкриментное поле, $rand = rand(1, 1000 - $limit), $limit - собственно количество записей.
Простое и экономное решение. Естественно если записей в таблице не много, то выборка получится довольно однообразная, и тогда лучше использовать order by rand, как выше посоветовали.
Общее количество записей (1000) можно вытаскивать еще одним простым запросом с MAX или COUNT(*) или данными из information schema. Но я из экономии ресурсов прописывал вручную.
Рандом - зло :)
Я делал примерно так (зная допустим что у меня уже в таблице 1000 записей или немногим больше):
SELECT ... FROM `table` WHERE `id` > $rand LIMIT $limit
где `id` - инкриментное поле, $rand = rand(1, 1000 - $limit), $limit - собственно количество записей.
Простое и экономное решение. Естественно если записей в таблице не много, то выборка получится довольно однообразная, и тогда лучше использовать order by rand, как выше посоветовали.
Общее количество записей (1000) можно вытаскивать еще одним простым запросом с MAX или COUNT(*) или данными из information schema. Но я из экономии ресурсов прописывал вручную.
Спустя 3 часа, 50 секунд (26.03.2011 - 09:06) Trianon написал(а):
kirik
Автор, очевидно, стремится избежать неприятностей в ситуации, когда MAX(id) существенно превышает количество имеющихся записей.
Автор, очевидно, стремится избежать неприятностей в ситуации, когда MAX(id) существенно превышает количество имеющихся записей.
Цитата |
SELECT ... FROM `table` WHERE `id` > $rand LIMIT $limit |
(Полагаю, ORDER BY id был забыт случайно - без него LIMIT смысла не имеет. )
если id имеющихся записей будут распределены так, что к моменту запроса все они окажутся больше тысячи - запрос станет возвращать одну за другой одинаковые выборки из $limit строк.
автор ориентируется на запрос
"SELECT tbl FROM TABLE WHERE number = " . rand(1, $max);
который при уникальном индексе на поле будет давать резульат, незначительно отличающийся от выборки по первичному ключу.
Добавление и удаление строк, правда, станет задачей повеселее. Удаление схематично:
$del = [ SELECT number FROM tbl WHERE id = $del_id ] ;
$max = [ SELECT MAX(number) FROM tbl ] ;
[ DELETE FROM tbl WHERE id = $del_id ] ;
if($del < $max)
[ UPDATE tbl SET number = $del WHERE number = $max ] ;
C другой стороны можно ж и процедурку накатать хранимую, или триггер.
Спустя 16 часов, 18 минут, 10 секунд (27.03.2011 - 01:24) kirik написал(а):
Цитата (Trianon @ 26.03.2011 - 01:06) |
если id имеющихся записей будут распределены так, что к моменту запроса все они окажутся больше тысячи - запрос станет возвращать одну за другой одинаковые выборки из $limit строк. |
Это так.. у меня на практике таких больших "дыр" не было.. В таком случае можно вытаскивать значения MIN и MAX для поля id, тогда выборка будет немного корректнее, но в два запроса.
Сортировку по id да, забыл..
