[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Вывод из базы mySQL
dzisay
Имеется база типа:

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 Вы правы сейчас подправлю.

Спустя 2 минуты, 18 секунд (24.03.2011 - 19:39) Trianon написал(а):
dzisay
Так ведь и -7 нету. smile.gif
Эдак Вы долго будете подправлять.

Спустя 2 минуты, 22 секунды (24.03.2011 - 19:41) sergeiss написал(а):
dzisay - а я так спрошу: свои-то какие соображения есть по этому поводу?

Спустя 12 минут, 36 секунд (24.03.2011 - 19:54) dzisay написал(а):
Trianon
Подправил в описании вопроса.

sergeiss
Думаю что нужно конструировать цикл до появления нужного значения...только вот как именно sad.gif

Спустя 12 минут, 42 секунды (24.03.2011 - 20:07) neadekvat написал(а):
Но ноль не является положительным числом :)

Ну, ладно.. если с перебором, с помощью 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 минуты работы, да еще и перекур сделать успеть можно smile.gif

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

Внимательно посмотрите подпись под моей аватаркой smile.gif

Спустя 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, 'авымваывамывамывам');

Спустя 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

Спустя 2 минуты, 1 секунда (24.03.2011 - 20:32) neadekvat написал(а):
dzisay, вы свои данные хоть подставили в запрос?

Возьмите имя таблицы и столбца в ``
Плюс, мой код сработает, если значения 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'];
}

Спустя 23 секунды (24.03.2011 - 20:36) neadekvat написал(а):
Цитата (neadekvat @ 24.03.2011 - 20:32)
Возьмите имя таблицы и столбца в ``
Плюс, мой код сработает, если значения number не могут повторяться


Спустя 4 минуты, 34 секунды (24.03.2011 - 20:41) dzisay написал(а):
smile.gif Заработало, а что на счёт метода на SQL стесняюсь спросить.

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

Спустя 4 минуты, 39 секунд (24.03.2011 - 20:59) dzisay написал(а):
Ну ладно и на этом огромное спасибо smile.gif

Спустя 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)
Оно есть... Я только вспомню, как делал, и напишу.

Я не отрицал этого smile.gif Просто сходу такое не решить (нужно повкуривать в стандартные функции). Разве что какой-нибудь хитрой логикой, которую понять даже по написанному не сразу получится.

Хотя, я, возможно, все-таки
Цитата (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 завязанное будет smile.gif

Правда, Дмитрий, поясни, пожалуйста, почему 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:

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 у товарища уже есть.
А значения в столбиках идентичны не для всех строк.

Это я к тому, что формально товарищ из-под такого обвинения выползет не запачкавшись.
А если он таким образом решил нас запутать, то это очень хитрый товарищ smile.gif

Лично я склонен предположить, что он, распределяя некий дискретный ресурс с приоритетом в начале диапазона (места в зале кинотеатра, часы регистрации брака в ЗАГСе, и т.п.) , отыскивает дырки свободных слотов .

Спустя 21 минута, 44 секунды (25.03.2011 - 10:31) neadekvat написал(а):
Trianon, ух ты smile.gif Спасибо.

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

Спустя 4 часа, 20 минут, 30 секунд (25.03.2011 - 14:53) dzisay написал(а):
Цитата (Trianon @ 25.03.2011 - 07:10)
это очень хитрый товарищ smile.gif

Ну здесь вы переборщили, я всего лишь новичок rolleyes.gif

Спустя 10 минут, 33 секунды (25.03.2011 - 15:04) dzisay написал(а):
А конструкция сия мне нужна для последующего рандомного вывода строки, придав ей уже конкретное значение:

 
$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? Слышал, что это довольно ресурсоемкое решение.

Спустя 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? Слышал, что это довольно ресурсоемкое решение.

А ты думаешь, что предложенный тебе ранее вариант будет выполняться мгновенно? smile.gif

Если уж тебе очень хочется сделать в ПХП, то тогда всё равно не надо "восстанавливать непрерывность". Просто запиши полученные id в массив и выбери оттуда произвольное число. Только время замерь... Очень может быть, что внутри SQL быстрее получится.

Спустя 9 минут, 15 секунд (25.03.2011 - 20:13) dzisay написал(а):
Цитата (sergeiss @ 25.03.2011 - 17:04)
А ты думаешь, что предложенный тебе ранее вариант будет выполняться мгновенно? smile.gif

Не спорю, что создание строк будет массивным.
Я же борюсь за мгновенность и простоту вывода строк huh.gif - основной задачей базы.

Спустя 9 часов, 51 минута, 53 секунды (26.03.2011 - 06:05) kirik написал(а):
dzisay
Рандом - зло :)
Я делал примерно так (зная допустим что у меня уже в таблице 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) существенно превышает количество имеющихся записей.

Цитата
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 да, забыл.. smile.gif
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.