Форум: "Начинающим";
Текущий архив: 2009.04.05;
Скачать: [xml.tar.bz2];
ВнизПоиск "дырки" в записях Найти похожие ветки
← →
Maacheba (2009-02-12 19:05) [0]Есть таблица, назовем ее "MyTable", формат:
Number | FlagDeleting
Number - число, FlagDeleting - тоже число, если равно 1 - то запись считается уничтоженной в запросах (но физически из таблицы не удаляется).
Задача: найти первую свободную "дырку" в последовательности Number среди не помеченных на удаление записях.
Пример:
Number | FlagDeleting
================
1 | 0
6 | 0
4 | 0
2 | 0
Правильный ответ: 3
Еще пример:
Number | FlagDeleting
================
1 | 0
2 | 1
3 | 0
4 | 0
Правильный ответ: 2
Чтобы найти дырку - с успехом срабатывает такой код:SELECT MyTable.Number + 1 from MyTable left join
MyTable m on (MyTable.Number + 1 = m.Number) where "
(m.Number is null) and (MyTable.Number+1 > X)
Где "X" - фактически задает тот лимит с которого искать дырку. Если X = 0, то дырка начинает искаться с числа 1, если задать X=5, то дырка начинает искаться 6 и т.д.
Вопрос в том, что нужно учесть столбец FlagDeleting, помеченые как удаленные записи просто не рассматривать. Если делать так:SELECT MyTable.Number + 1 from MyTable left join
MyTable m on (MyTable.Number + 1 = m.Number) where "
(m.Number is null) and (MyTable.Number+1 > X) and (MyTable.FlagDeleting=0)
То такой запрос возвращает NULL.
Если условиеMyTable.FlagDeleting=0
заменить наm.FlagDeleting=0
или их сочетание - тоже самое.
Не понимаю, почему так происходит и как это исправить?
P.S. База - SQLite
← →
Palladin © (2009-02-13 08:04) [1]Number надеюсь не используется как первичный ключ?
← →
Jack128_ (2009-02-13 08:35) [2]
> m.FlagDeleting=0
это условие помести в
left join
MyTable m on (MyTable.Number + 1 = m.Number) and m.FlagDeleting<>0
← →
Jack128_ (2009-02-13 08:38) [3]
> left join
> MyTable m on (MyTable.Number + 1 = m.Number) and m.FlagDeleting=0
Хотя навскидку моно и оставить в where, примерно в таком виде:
where (MyTable.Number+1 > X) and ((m.Number is null) or (MyTable.FlagDeleting=0))
← →
Jack128_ (2009-02-13 09:23) [4]Блин.
>
> where (MyTable.Number+1 > X) and ((m.Number is null) or
> (m.FlagDeleting=0))
вобщем сам разберешся, смысл, надеюсь понял..
← →
Johnmen © (2009-02-13 09:45) [5]
> Maacheba (12.02.09 19:05)
Просто в условие соединения добавитьand (m.FlagDeleting=0)
← →
Maacheba (2009-02-13 11:57) [6]Никто не поможет?
← →
Maacheba (2009-02-13 12:11) [7]Ух, почему-то при просмотре ветки она закешировалась, думал нет новых ответов...
Спасибо всем за помощь!
← →
Maacheba (2009-02-13 12:12) [8]
> Number надеюсь не используется как первичный ключ?
нет, конечно.
← →
MsGuns © (2009-02-13 12:14) [9]Такой запрос написать не проблема, но он будет выполняться медленно, однако механизм такого "резервирования" какой-то неуклюжий. Если Вы объясните великий смысл этого загадочного Number, нам будет много проще помочь
← →
MsGuns © (2009-02-13 12:15) [10]Пардон, не запрос, а хранимку или функцию (не знаком с лайтом)
← →
Кщд (2009-02-13 12:29) [11]>Поиск "дырки" в записях
не ясно, какой смысл в этом поиске, если база данных - многопользовательская
← →
Виталий Панасенко (2009-02-13 12:51) [12]
> Кщд (13.02.09 12:29) [11]
лайт, кажись, как раз однопользовательский
← →
Кщд (2009-02-13 13:02) [13]>Виталий Панасенко (13.02.09 12:51) [12]
как-будто многопользовательская...
http://www.sqlite.org/faq.html#q5
Multiple processes can have the same database open at the same time. Multiple processes can be doing a SELECT at the same time. But only one process can be making changes to the database at any moment in time, however.
← →
Johnmen © (2009-02-13 13:03) [14]Даже для однопользовательского проблема "дырок" - полная чушь...
:)
← →
Maacheba (2009-02-13 20:18) [15]Чего-то не получается :(
Давайте на реальной базе уж, чтобы мозги не пудрить.
NUM_GLOBAL - как раз та переменная, в которой надо найти дырку.
Activity - признак активности. Если 0 - то значит запись считается "удаленной", если больше нуля - значит не удалена.
Сам пример базы:
http://pic.ipicture.ru/uploads/090213/6tnSNRtsIy.gif
> > where (MyTable.Number+1 > X) and ((m.Number is null) or
>
> > (m.FlagDeleting=0))
>
> вобщем сам разберешся, смысл, надеюсь понял..
не разобрался :(
Сделал такой запрос:SELECT Clients.NUM_GLOBAL + 1 from Clients left join Clients c on (Clients.NUM_GLOBAL + 1 = c.NUM_GLOBAL) where (Clients.NUM_GLOBAL+1 > 0) and ( (c.Activity=0) or (c.NUM_GLOBAL is null) )
Но он возвращает: 3 (вместо правильного ответа 1): http://pic.ipicture.ru/uploads/090213/X35ThyceyM.gif
> это условие помести в
>
> left join
сделал такой запрос:SELECT Clients.NUM_GLOBAL + 1 from Clients left join Clients c on (Clients.NUM_GLOBAL + 1 = c.NUM_GLOBAL) and (c.Activity>0) where (Clients.NUM_GLOBAL+1 > 0) and (c.NUM_GLOBAL is null)
Но он тоже возвращает: 3 - http://pic.ipicture.ru/uploads/090213/S5jJqY2BsO.gif
НИ-ЧЕ-ГО не понимаю (
← →
Maacheba (2009-02-14 12:40) [16]Может SQLite чего-то не так делает...
← →
sniknik © (2009-02-14 14:21) [17]> Может SQLite чего-то не так делает...
конечно не то... ведь он делает то, что ему говорят(/пишут), а не то что при этом думают...
хотя не знаю что там с SQLite, но и для access логика запросов неверная (не говоря уже об идее поиска ничего не значащих "дырок")
вот так работает нормально (access!!!, но как видно логика изменена)SELECT TOP 1 t1.NUM_GLOBAL + 1 AS [Дырка] FROM
Clients t1 LEFT JOIN Clients t2 ON (t1.NUM_GLOBAL + 1) = t2.NUM_GLOBAL AND t2.Activity = 0
WHERE t2.NUM_GLOBAL IS NULL
← →
Maacheba (2009-02-14 15:26) [18]sniknik © (14.02.09 14:21) [17]
это аналог выражения, которое я выше написал:SELECT Clients.NUM_GLOBAL + 1 from Clients left join Clients c on (Clients.NUM_GLOBAL + 1 = c.NUM_GLOBAL) and (c.Activity>0) where (Clients.NUM_GLOBAL+1 > 0) and (c.NUM_GLOBAL is null)
только Activity>0 ты заменил на Activity = 0.
SQLite возвращает при этом запросе: 2
Хотя правильный ответ: 1
http://s52.radikal.ru/i137/0902/c9/ef9e9b991381.jpg
(зеркало): http://pic.ipicture.ru/uploads/090214/1x0B2LkXXj.gif
← →
sniknik © (2009-02-14 17:20) [19]> это аналог выражения, которое я выше написал:
ну пусть будет аналог.
> SQLite возвращает при этом запросе: 2
> Хотя правильный ответ: 1
а до того было, у "аналога"
> Но он тоже возвращает: 3 - http://pic.ipicture.ru/uploads/090213/S5jJqY2BsO.gif
на исходных данных
> Еще пример:
>
> Number | FlagDeleting
> ================
> 1 | 0
> 2 | 1
> 3 | 0
> 4 | 0
>
> Правильный ответ: 2
а теперь возвращает бывшее правильное 2... и опять не нравиться, теперь почему то правильным стала еденица. как понять тебя Саид?.
← →
sniknik © (2009-02-14 17:41) [20]и кстати, 1-у и не должно находить... она на первой записи и поэтому не может быть "дыркой", т.к. это начало отсчета. и с какой цифры бы оно не начиналось... в общем "дырки" это то что между, а начало с краю.
постаноу=вку задачи надо пересмотреть если тебе нужны не дырки а отсутствующие в каком то периоде/списке.
← →
Maacheba (2009-02-14 19:05) [21]sniknik © (14.02.09 17:20) [19]
а до того было, у "аналога"
написано не просто "аналог", а "это аналог выражения... только Activity>0 ты заменил на Activity = 0"
sniknik © (14.02.09 17:20) [19]
а теперь возвращает бывшее правильное 2... и опять не нравиться
стоит заметить, что взяты разные примеры. В первом посте приведены данные от балды, чтобы показать СУТЬ задачи.
Само же тестирование делалось на реальной базе: http://pic.ipicture.ru/uploads/090213/6tnSNRtsIy.gif - и здесь правильный ответ: 1
sniknik © (14.02.09 17:41) [20]
постаноу=вку задачи надо пересмотреть если тебе нужны не дырки а отсутствующие в каком то периоде/списке
ну можно описать существующий смысл:
есть клиенты и у каждого клиента есть номер билета NUM_GLOBAL. Со временем клиенты могут удаляться физически (как запись из базы), а могут быть помечены как удаленные, при этом Activity выставляется в ноль. Для логики программы записи, где Activity стоит в 0 тоже самое, что этой записи вообще бы не было.
В таких условиях надо уметь искать НАИМЕНЬШИЙ доступный номер билета для выделения его новому клиенту. Нумерация билетов начинается с 1.
P.S. Задача такова, как я ее описал. Крики "ты лох" и "ты ничего не понимаешь", а также "тебе нужно не это, а другое" - просьба не озвучивать.
← →
sniknik © (2009-02-14 19:42) [22]> Само же тестирование делалось на реальной базе: http://pic.ipicture.ru/uploads/090213/6tnSNRtsIy.gif - и здесь правильный ответ: 1
вообще то, по описанию в [0], и здесь правильный ответ 2, или второй пример в [0] приводит неправильный ответ.
> P.S. Задача такова, как я ее описал.
да ну? а почему тогда при одинаковых исходных данных в разных постах у тебя верными считаются разные цифры?
и если вначале только СУТЬ, то почему из запроса не взята тоже только она и не подставлены сравнение на нужные значения? почему запрос взят as is?
> при этом Activity выставляется в ноль.
а в [0] во втором примере (на что я ориентировался) удаленной считается с FlagDeleting(Activity?) = 1
> В таких условиях надо уметь искать НАИМЕНЬШИЙ доступный номер билета для выделения его новому клиенту. Нумерация билетов начинается с 1.
ну так... введи точку отсчета - не стираемую запись со значением 0 и все, мой запрос будет работать... если ты конечно определишься наконец что у тебя считается удаленным а что нет, и поправишь под это, если конечно способен... а то ты видишь в выборке того что есть и присоединение к этому равнозначность выборке того что нет по одному способу игнорируя другой.
> Крики "ты лох" и "ты ничего не понимаешь", а также "тебе нужно не это, а другое" - просьба не озвучивать.
где реально кто то говорил, что "ты лох"? ну а то что "ты ничего не понимаешь" я думаю очевидно, иначе бы не спрашивал.
← →
Johnmen © (2009-02-14 19:53) [23]
> Maacheba (14.02.09 19:05) [21]
Да-да, вместо того, чтобы возбухать, надо осознать, что ты ничего не понимаешь, и сделать попытку понять.
ЗЫ
Впрочем, если тебе завтра дадут задачу сделать велик с квадратными колесами, то ты можешь читать мантру "Задача такова, как я ее описал"
:))
← →
Maacheba (2009-02-14 21:33) [24]
> ну так... введи точку отсчета - не стираемую запись со значением
> 0 и все
без введения такой записи задачу средствами SQL решить невозможно?
> вообще то, по описанию в [0], и здесь правильный ответ 2,
> или
блин... Я прошу прощения, что запутал, но в первом посте колонка FlagDeleting, она имеет противоположное значение реальной колонки Activity из реальной базы.
Реально запись считается удаленной, если Activity в 0. Если не ноль - то запись актуальна.
Давайте рассуждать о реальной базе теперь. Если нужно - я переделаю примеры:
NUM_GLOBAL | Activity
================
1 | [не ноль]
6 | [не ноль]
4 | [не ноль]
2 | [не ноль]
Правильный ответ: 3
Еще пример:
NUM_GLOBAL | Activity
================
1 | [не ноль]
2 | 0
3 | [не ноль]
4 | [не ноль]
Правильный ответ: 2
← →
Сергей М. © (2009-02-14 23:21) [25]
> Давайте рассуждать о реальной базе теперь
Ты ее сам лепил, базу эту ?
Или она досталась тебе в тяжелое наследство ?
Только честно уж, агрессивный ты наш) ..
← →
Германн © (2009-02-15 00:55) [26]
> Только честно уж, агрессивный ты наш) ..
Против партизан почти нет приёмов. И это доказывают все исторические примеры, начинаю с середины прошлого века. А уж против агрессивных?
:)
← →
Maacheba (2009-02-15 13:17) [27]Народ, задача остается пока, решение не придумал. Кратко сформулирую задачу:
есть клиенты и у каждого клиента есть номер билета NUM_GLOBAL. Со временем клиенты могут удаляться физически (как запись из базы), а могут быть помечены как удаленные, при этом Activity выставляется в ноль. Для логики программы записи, где Activity стоит в 0 тоже самое, что этой записи вообще бы не было.
В таких условиях надо уметь искать НАИМЕНЬШИЙ доступный номер билета для выделения его новому клиенту. Нумерация билетов начинается с 1.
Примеры:
NUM_GLOBAL | Activity
================
1 | [не ноль]
6 | [не ноль]
4 | [не ноль]
2 | [не ноль]
Правильный ответ: 3 (потому что это наименьшее число, начиная с 1, для которого запись отсутствует или activity равно нулю).
Еще пример:
NUM_GLOBAL | Activity
================
1 | [не ноль]
2 | 0
3 | [не ноль]
4 | [не ноль]
Правильный ответ: 2 (потому что это наименьшее число, начиная с 1, для которого запись отсутствует или activity равно нулю).
← →
Maacheba (2009-02-15 18:30) [28]Средствами SQL сделать это невозможно? ((
Время поджимает, поэтому сделаю так:
1) запрос на все данные и сортировка ORDER BY NUM_GLOBAL
2) вручную пробегаюсь от первой записи до последней, если следующая запись по NUM_GLOBAL отличается от предыдущей более, чем на единицу или если в следующей записи Activity=0, то значит нашел.
Правда, странно что это нельзя реализовать чисто в SQL, лишняя работа (
← →
Maacheba (2009-02-15 18:32) [29]Удалено модератором
Примечание: Обсуждение модерирования
← →
sniknik © (2009-02-15 19:20) [30]> сходу решения никто не придумал.
да неужто прям бином Ньютона?... ;), чуток исправить то что я приводил (добавить поиск начала) и все будет под новые "правила"... пока ты их опять не поменял.
правда это сработает (с исправлениями конечно), могу исправить, для аксесс, mssql, vfp, даже под firebird который очень слабо знаю, и даже под нелюбимый оракл.... но вот для SQLite который в глаза не видел, и желания изучать нет... не обессудь.
> Сразу видно - вопрос для начинающих )
причем тут вопрос? ТЫ начинающий. т.к. ведешь себя соответственно.
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2009.04.05;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.006 c