![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Поиск "дырки" в записях [D7, SQLite]
Maacheba © (2009-02-12 19:05:00)Есть таблица, назовем ее "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
sniknik (2009-02-15 19:20:00) [1]> сходу решения никто не придумал.
да неужто прям бином Ньютона?... ;), чуток исправить то что я приводил (добавить поиск начала) и все будет под новые "правила"... пока ты их опять не поменял.
правда это сработает (с исправлениями конечно), могу исправить, для аксесс, mssql, vfp, даже под firebird который очень слабо знаю, и даже под нелюбимый оракл.... но вот для SQLite который в глаза не видел, и желания изучать нет... не обессудь.
> Сразу видно - вопрос для начинающих )
причем тут вопрос? ТЫ начинающий. т.к. ведешь себя соответственно.
Maacheba (2009-02-15 18:32:00) [2]Удалено модератором
Примечание: Обсуждение модерирования
Maacheba (2009-02-15 18:30:00) [3]Средствами SQL сделать это невозможно? ((
Время поджимает, поэтому сделаю так:
1) запрос на все данные и сортировка ORDER BY NUM_GLOBAL
2) вручную пробегаюсь от первой записи до последней, если следующая запись по NUM_GLOBAL отличается от предыдущей более, чем на единицу или если в следующей записи Activity=0, то значит нашел.
Правда, странно что это нельзя реализовать чисто в SQL, лишняя работа (
Maacheba (2009-02-15 13:17:00) [4]Народ, задача остается пока, решение не придумал. Кратко сформулирую задачу:
есть клиенты и у каждого клиента есть номер билета 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 равно нулю).
Германн (2009-02-15 00:55:00) [5]
> Только честно уж, агрессивный ты наш) ..
Против партизан почти нет приёмов. И это доказывают все исторические примеры, начинаю с середины прошлого века. А уж против агрессивных?
:)
Сергей М. (2009-02-14 23:21:00) [6]
> Давайте рассуждать о реальной базе теперь
Ты ее самлепил, базу эту ?
Или она досталась тебе в тяжелое наследство ?
Только честно уж, агрессивный ты наш) ..
Maacheba (2009-02-14 21:33:00) [7]
> ну так... введи точку отсчета - не стираемую запись со значением
> 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
Johnmen (2009-02-14 19:53:00) [8]
> Maacheba (14.02.09 19:05) [21]
Да-да, вместо того, чтобы возбухать, надо осознать, что ты ничего не понимаешь, и сделать попытку понять.
ЗЫ
Впрочем, если тебе завтра дадут задачу сделать велик с квадратными колесами, то ты можешь читать мантру "Задача такова, как я ее описал"
:))
sniknik (2009-02-14 19:42:00) [9]> Само же тестирование делалось на реальной базе: http://pic.ipicture.ru/uploads/090213/6tnSNRtsIy.gif- и здесь правильный ответ: 1
вообще то, по описанию в [0], и здесь правильный ответ 2, или второй пример в [0] приводит неправильный ответ.
> P.S. Задача такова, как я ее описал.
да ну? а почему тогда при одинаковых исходных данных в разных постах у тебя верными считаются разные цифры?
и если вначале только СУТЬ, то почему из запроса не взята тоже только она и не подставлены сравнение на нужные значения? почему запрос взят as is?
> при этом Activity выставляется в ноль.
а в [0] во втором примере (на что я ориентировался) удаленной считается с FlagDeleting(Activity?) = 1
> В таких условиях надо уметь искать НАИМЕНЬШИЙ доступный номер билета для выделения его новому клиенту. Нумерация билетов начинается с 1.
ну так... введи точку отсчета - не стираемую запись со значением 0 и все, мой запрос будет работать... если ты конечно определишься наконец что у тебя считается удаленным а что нет, и поправишь под это, если конечно способен... а то ты видишь в выборке того что есть и присоединение к этому равнозначность выборке того что нет по одному способу игнорируя другой.
> Крики "ты лох" и "ты ничего не понимаешь", а также "тебе нужно не это, а другое" - просьба не озвучивать.
где реально кто то говорил, что "ты лох"? ну а то что "ты ничего не понимаешь" я думаю очевидно, иначе бы не спрашивал.
Maacheba (2009-02-14 19:05:00) [10]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 17:41:00) [11]и кстати, 1-у и не должно находить... она на первой записи и поэтому не может быть "дыркой", т.к. это начало отсчета. и с какой цифры бы оно не начиналось... в общем "дырки" это то что между, а начало с краю.
постаноу=вку задачи надо пересмотреть если тебе нужны не дырки а отсутствующие в каком то периоде/списке.
sniknik (2009-02-14 17:20:00) [12]> это аналог выражения, которое я выше написал:
ну пусть будет аналог.
> SQLite возвращает при этом запросе: 2
> Хотя правильный ответ: 1
а до того было, у "аналога"
> Но он тоже возвращает: 3- http://pic.ipicture.ru/uploads/090213/S5jJqY2BsO.gif
на исходных данных
> Еще пример:
>
> Number | FlagDeleting
> ================
> 1 | 0
> 2 | 1
> 3 | 0
> 4 | 0
>
> Правильный ответ: 2
а теперь возвращает бывшее правильное 2... и опять не нравиться, теперь почему то правильным стала еденица. как понять тебя Саид?.
Maacheba (2009-02-14 15:26:00) [13]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 14:21:00) [14]> Может 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 12:40:00) [15]Может SQLite чего-то не так делает...
Maacheba (2009-02-13 20:18:00) [16]Чего-то не получается :(
Давайте на реальной базе уж, чтобы мозги не пудрить.
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
НИ-ЧЕ-ГО не понимаю (
Johnmen (2009-02-13 13:03:00) [17]Даже для однопользовательского проблема "дырок" - полная чушь...
:)
Кщд (2009-02-13 13:02:00) [18]>Виталий Панасенко (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.
Виталий Панасенко (2009-02-13 12:51:00) [19]
> Кщд (13.02.09 12:29) [11]
лайт, кажись, как раз однопользовательский
Кщд (2009-02-13 12:29:00) [20]>Поиск "дырки" в записях
не ясно, какой смысл в этом поиске, если база данных - многопользовательская