проблема с исправлением dbf в Fox
40001 1
40001 2
40001 3
40001 сколько необходимо
40002 1
40002 2
40002 3
40002 сколько необходимо
А в данный момент выглядит так:
40001 1
40001 2
40001 3
40001 сколько необходимо
40001 1
40001 2
40001 3
40001 сколько необходимо
40002 1
40002 2
40002 3
40002 сколько необходимо
40002 1
40002 2
40002 3
40002 сколько необходимо
Вообщем суть проблемы: Задвоились все строки и как написать запрос на их удаление ни как не могу придумать, т.к. данные ничем не различаются.
Помогите пожалуйста.
1. Есть ли в фоксе ранжирующие оконные функции? что-то типа row_number() которая нумерует строки в результирующей выборке, если есть - использовать ее, пронумеровать строки и удалить все строки с номером 1 или номером 2.
2. Если нет, то как вариант, добавить колонку в таблицу, в эту колонку проставить последовательно номера (либо сразу добавить колонку identity, ежели так можно в фоксе). После этого сделать обычный запрос с группировкой и удалить те строки, в которых значение этого поля будет максимальным или минимальным в группе. после этого удалить колонку.
3. Создать временную таблицу, перелить туда обычным запросом сгруппированные данные из таблицы с дубликатами. Удалить все данные из таблицы дубликатов, залить в нее данные из временной. Удалить временную. Этот способ может быть неудобен если в таблице есть первичный ключ, на который ссылаются другие таблицы.
как-то так, что приходит в голову на первый взгляд. удачи.
1. Есть ли в фоксе ранжирующие оконные функции? что-то типа row_number() которая нумерует строки в результирующей выборке, если есть - использовать ее, пронумеровать строки и удалить все строки с номером 1 или номером 2.
2. Если нет, то как вариант, добавить колонку в таблицу, в эту колонку проставить последовательно номера (либо сразу добавить колонку identity, ежели так можно в фоксе). После этого сделать обычный запрос с группировкой и удалить те строки, в которых значение этого поля будет максимальным или минимальным в группе. после этого удалить колонку.
3. Создать временную таблицу, перелить туда обычным запросом сгруппированные данные из таблицы с дубликатами. Удалить все данные из таблицы дубликатов, залить в нее данные из временной. Удалить временную. Этот способ может быть неудобен если в таблице есть первичный ключ, на который ссылаются другие таблицы.
как-то так, что приходит в голову на первый взгляд. удачи.
Спасибо за предложение, но:
1. такой функции насколько мне известно нет.
2. неподходящий вариант, т.к. при добавлении колонки может сбиться структура т.к. таблица постоянно взаимодействует с другими таблицами и изменение ее может привести к окончательной крышке для общей базы.
3. тот же случай что и с пунктом 2...
Но все равно громадное спасибо за попытку помочь.
Мне знакомые советовали в принципе вариант как можно решить эту проблему, но они тоже работают только с sql server потому не знают как реализовать функционально это решение. Суть заключается в том, что нужно создать цикл который брал за основу вначале первую строку первого столбца и если данные равны второй строке, то сравнивал первую строку второго столбца и т.д. и если находил совпадение, то удалял его... Но как это реализовать даже приблизительно не представляю...
1. такой функции насколько мне известно нет.
2. неподходящий вариант, т.к. при добавлении колонки может сбиться структура т.к. таблица постоянно взаимодействует с другими таблицами и изменение ее может привести к окончательной крышке для общей базы.
3. тот же случай что и с пунктом 2...
Но все равно громадное спасибо за попытку помочь.
1. очень жаль..
2. вот почему не надо запросы писать через select *, если бы все запросы были написаны изначально нормально, то проблем бы не было.
3. если с таблицей идет активная работа, то может создать таблицу дубликат полностю идентичную, но с другим именем, залить туда все данные, а потом одномоментно в одной транзакции с высоким уровнем изоляции "переключить" таблицы, поменяв имя одно на другое. если в фоксе блокировки реализованы нормально, ничего страшного не произойдет, другие транзакции просто чуток "подождут" и все. но лучше конечно сделать тестовый слепок бд и проверить сначала на нем. потом либо руками "дозалить" данные которые успели попасть в старую таблицу до переключения, либо операцию по заполнению временной таблицы и само переключение делать вообще в одной транзакции, тогда возможно другим запросам придется подождать подольше =)
Мне знакомые советовали в принципе вариант как можно решить эту проблему, но они тоже работают только с sql server потому не знают как реализовать функционально это решение. Суть заключается в том, что нужно создать цикл который брал за основу вначале первую строку первого столбца и если данные равны второй строке, то сравнивал первую строку второго столбца и т.д. и если находил совпадение, то удалял его... Но как это реализовать даже приблизительно не представляю...
Суть тут в чем, вот это первую строку и есть основная проблема, в рсубд нет такого понятия как первая-последняя строки, строки должны уникально идентифицироваться ключем. Если этого ключа нет - то формально бд не может отличить одну строку от другой. вот как вы напишете команду delete если у вас с точки зрения бд две абсалютно одинаковые строки, какое условие поставите чтоб "удалить одну а вторую не трогать", в том-то и проблема. был бы ключ - не надо было б циклов, все одним запросом делается. По этому в такой ситуации у вас, имхо, два пути - либо как-то пронумеровать строки (например как я предложил в п.1 или 2, или поискать, может в фоксе есть свои специфичные способы нумерации), либо как-то отработать на уровне множества, т.е. через временную таблицу.
upd:
пока писал, пришла еще одна мысль. как насчет курсоров, в фоксе есть такое? при помощи операции fetch курсора теоретически можно было бы брать именно по одной строке и сравнивать ее с предыдущей, при этом правда надо обеспечить правильный порядок строк в самом курсоре иначе в таком сравнении будет мало толку. и вот тут как раз курсор можно перебирать в том самом цикле, м.б. это вам советовали? только сразу учтите что это будет гораздо дольше чем со множествами или одним запросом. И не знаю как в фоксе, но в сиквеле пришлось бы создавать динамический курсор для обновления, а раз динамический то данные в нем могли бы изменятся, тогда вероятность получить несогласованные данные увеличивается, либо пришлось бы класть хорошую такую блокировку на таблицу, и т.к. курсор и цикл - операция затратная (заведомо медленнее чем один два-запроса), то блокировка бы заняла много времени, чем потенциально создала бы проблемы если с таблицей идет активная работа. Но как там у вас в фоксе - почитайте обязательно, это я описал потенциальные грабли в сиквеле, просто чтоб вы имели ввиду что такие проблемы могут быть.