:: Visual Foxpro, Foxpro for DOS
Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Есть желание написать универсальную процедуру, которая ВНЕ зависимости от структуры и наличия/отсутствия ключей выберет все повторяющиеся записи.

Пока ехал в автобусе пришли 2 идеи:

1) Перебрать в цикле все поля и собрать полный ключ по всем полям. Без индекса и на огромной базе будут тормоза, ибо декартово произведение по строкам получится.

2) Думал выбрать уникальные записи (типа SELECT DISTINCT * ...) и количество сравнить с числом записей. Но конструкция не взлетела из-за наличия мемо-полей.

3) Вычитывать что-то ключа? А если его нет?

Наверняка кто-то да писал подобное, ибо чистый Фокс.


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
А SELECT COUNT(*) AS cnt ... GROUP BY ... HAVING cnt>1 ?
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
Select SYS(2017, 'id', 0, 3) from ...
Ratings: 0 negative/1 positive
Re: Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
of63
А SELECT COUNT(*) AS cnt ... GROUP BY ... HAVING cnt>1 ?А SELECT COUNT(*) AS cnt ... GROUP BY ... HAVING cnt>1 ?

Еще раз. В GROUP BY можно, конечно, записать строку, собранную так:

FOR i=1 TO FCOUNT()
lcFiels = lcField + FIELD(i) + ', '
ENDFOR

Но МЕМО-поле нельзя использовать в группировке.


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Taran
Select SYS(2017, 'id', 0, 3) from ...

SYS(2017) - Значение контрольной суммы текущей записи в текущей рабочей области.SYS(2017) - Значение контрольной суммы текущей записи в текущей рабочей области.

Красиво! Ведь читал про нее, а на практике не приходилось использовать.
Спасибо, Олег, завтра буду пробовать.


------------------
"Veni, vidi, vici!"(с)




Исправлено 1 раз(а). Последнее : sphinx, 17.08.17 19:22
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
sphinx
of63
А SELECT COUNT(*) AS cnt ... GROUP BY ... HAVING cnt>1 ?А SELECT COUNT(*) AS cnt ... GROUP BY ... HAVING cnt>1 ?

Еще раз. В GROUP BY можно, конечно, записать строку, собранную так:

FOR i=1 TO FCOUNT()
lcFiels = lcField + FIELD(i) + ', '
ENDFOR

Но МЕМО-поле нельзя использовать в группировке.
Можно сигнатуру от этого поля использовать SYS(2007, ...)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
of63
Можно сигнатуру от этого поля использовать SYS(2007, ...)Можно сигнатуру от этого поля использовать SYS(2007, ...)

А что, неплохая идея!


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Все наверное, даже еще проще. При динамическом сборе ключа просто игнорировать мемо-поля, блоб-поля и прочие экзотические типы полей.


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
Рыба вот...
* forum.foxclub.ru
* sphinx 17.08.17 16:35:51
* Есть желание написать универсальную процедуру, которая ВНЕ зависимости от структуры и наличия/отсутствия ключей выберет все повторяющиеся записи.
Create Cursor _t (id i autoinc UNIQUE,;
Name V(10),;
Addr M)
Select _t
CursorSetProp("Buffering",1)
Insert into _t (Name, Addr) VALUES ('Иван', 'Березовая 15')
Insert into _t (Name, Addr) VALUES ('Марья', 'Березовая 15')
Insert into _t (Name, Addr) VALUES ('Иван', 'Березовая 15')
Insert into _t (Name, Addr) VALUES ('Иван', 'Березовая 12')
Insert into _t (Name, Addr) VALUES ('Семен', 'Сиреневая 12')
* чисто для примера чтобы показать mem`у и crc
Select id, Name, Left(Addr, 25), SYS(2017, 'id', 0, 3) as _sys from _t into cursor _source
Browse NOWAIT
Move Window _source to 0,0
* можно в один запрос
* вроде как можно и без подзапроса. Но нюансы там.
Select Count(id), _sys from (Select id, SYS(2017, 'id', 0, 3) as _sys from _t) _t2 group by _sys into cursor _1
Browse NOWAIT
Move Window _1 to 10,0
* но для теста и наглядности можно и в два
Select id, SYS(2017, 'id', 0, 3) as _sys from _t into cursor _11
Browse NOWAIT
Move Window _11 to 20,0
Select Count(id), _sys from _11 group by _sys into cursor _te2
Browse NOWAIT
Move Window _te2 to 30,0

+++
ну и да. При желании конечно HAVING прилепить.



Исправлено 2 раз(а). Последнее : Taran, 17.08.17 20:37
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
of63
sphinx
Но МЕМО-поле нельзя использовать в группировке.
Можно сигнатуру от этого поля использовать SYS(2007, ...)

sys(2017...) как раз для этого и сделана. Но проще. При ее использовании список полей в строку не надо собирать.
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Олег, да использовал такую. Хорошая ф-ия. Я из нее делал (начал с нее) что-то подобное буферизации в "современном" фоксе, чтобы отличать запись измененную от исходной. Т.е скопировал из БД нужные записи, добавил поля: RECNO() исходной записи, удалена ли, новое состояние удаленности, и сигнатуру полей исходной записи. Дальше правлю, добавляю, удаляю в этом курсоре... потом типа записываю курсор обратно в БД. Но потребовалось все-таки не сигнатура всех полей, а всех полей кроме служебных (чтобы отличить измененные записи от измененных), и вместо SYS(2017 нарисовалась сумма SYS(2007 ... Но эта комбинашка умерла )
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
of63
Олег, да использовал такую. Хорошая ф-ия. ...чтобы отличать запись измененную от исходной. ... Но потребовалось все-таки не сигнатура всех полей, а всех полей кроме служебных ...
Да, Олег. Я ж не тебя чтобы научить.
Так, к слову. Ну и чтобы Саня лишнее не мутил.

В sys(2017) как раз есть место где вписать исключаемые поля через запятую. У меня в примере там вписан 'id'.
А про отслеживание факта изменения... я стопорнулся на getfldstate(), curval(), oldval(). Да так и завис. ;)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
Я тоже на эти ф-ии забил, не понял, что с чем она сравнивает, хотя, возможно, они как-то похожи на мой доморощеный дубликат частички внешней таблицы. Все равно сделал по-другому (не буду рассказывать как, чтобы не шокировать ИК )

Про список исключений в SYS(2017 - Вау! Это бы пригодилось, а я че-то протупил... может их не было?...

Доб. Вобще-то русском хелпе вот так SYS(2017, cExpression [, nSeed [, nFlags]])
cExpression - Определяет список полей Записи (разделенных запятой), которые исключаются при вычислении контрольной суммы записи. Максимальная длина данной строки списка полей ограничена 256 -ю символами.
Если выражение cExpression - пусто, Visual FoxPro не исключает поля, кроме полей типа Memo и General .



Исправлено 2 раз(а). Последнее : of63, 17.08.17 21:12
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
Хотя конечно... Разрядность то небольшая по нынешним меркам у CRC32.
Можно налететь.
Т.е. я думаю ее надо рассматривать как "возможно дубль".
А уж при скане по этому значению и желании чего удалить сравнивать поля конкретно.
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
of63
Доб. Вобще-то русском хелпе вот так SYS(2017, cExpression [, nSeed [, nFlags]])
cExpression - Определяет список полей Записи (разделенных запятой), которые исключаются при вычислении контрольной суммы записи. ....
Если выражение cExpression - пусто, Visual FoxPro не исключает поля, кроме полей типа Memo и General .

Хмм. Чуток не понял мысль.
Я так думаю, что ели поля не указаны, то участвуют все кроме Memo и General. Но если в nFlags установлен бит 1, то и эти поля будут участвовать.
Собственно я в примере сделал акцент на мемо. Там три Ивана, но у одного адрес (Memo) отличается. И CRC у него становится другой.
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
of63

Сообщений: 25256
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
"" nFlags
Определяет дополнительный параметр вычисления CRC16 / CRC32
Версии Visual FoxPro < 8.0 используют механизм CRC16 = 16-битный алгоритм вычисления контрольной суммы для символьных данных. В настоящий момент Visual FoxPro обеспечивает вычисление КС как CRC32, 32-битный алгоритм. Устанавливая первый бит в данном параметре Вы можете управлять алгоритмом вычисления КС (контрольной суммы).
В следующей таблице представлены возможные значения параметра nFlags.
Значение Биты Описание
1 001 Вычисление контрольной суммы по алгоритму CRC32.
2 010 Включить также поля типа Memo при вычислении КС.

Раньше, только с CRC16 (без CRC32) невозможно было пользоваться, тексты "совпадали" буквально 1 на 1000 произвольных текстов. Это нереально плохо. CRC32 (2Г значений) может даст на 4 порядка (или меньше) лучшее качество... Это конечно тоже "плохо" но хоть что-то. Опять же произвольный текст можно ижеально сравнить только побайтно, любое "хеширование" (с уменьшением длины сообщения) не годится в принципе.
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Taran

Сообщений: 13625
Откуда: Красноярск
Дата регистрации: 16.01.2008
of63
"" nFlags....
Ага, пардон.
Конечно же говоря "бит 1", я имел ввиду второй бит.

of63
...CRC32 (2Г значений) может даст на 4 порядка (или меньше) лучшее качество... Это конечно тоже "плохо" но хоть что-то. Опять же произвольный текст можно ижеально сравнить только побайтно, любое "хеширование" (с уменьшением длины сообщения) не годится в принципе.

Ну собственно выше я об этом и упомянул.
В данной задаче sys(2017) вполне применимо на первом этапе для выявления потенциально возможных дублей.
А вторым делом уж производить сравнение полей на полную идентичность.
Как минимум сравнения сотен тысяч записей можно избежать.
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Олег-сан, дубли выбрал, полет пока нормальный.

Допилим, ежели что напильником. Идея ну очень понравилась.

На-ка тебе пиваса Уральского.


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
sphinx
Автор

Сообщений: 31185
Откуда: Каменск-Уральски
Дата регистрации: 22.11.2006
Олег-сан, дубли выбрал, полет пока нормальный.

Допилим, ежели что напильником. Идея ну очень понравилась.

На-ка тебе пиваса Уральского.


------------------
"Veni, vidi, vici!"(с)
Ratings: 0 negative/0 positive
Re: Как выбрать дубли?
Simple777

Сообщений: 33855
Дата регистрации: 05.11.2006
"Щедрый ты человек, боярин!.. Два пиваса проставил!" :bi:
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 25 alex;  (Гостей: 24)

© 2000-2024 Fox Club 
Яндекс.Метрика