powered by simpleCommunicator - 2.0.40     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как красиво отобрать первые встретившиеся записи?
36 сообщений из 36, показаны все 2 страниц
Как красиво отобрать первые встретившиеся записи?
    #37495462
Лунтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Например, есть таблица
1 Вася
1 Петя
1 Ваня
2 Аня
2 Таня
2 Маня

Нужно получить
1 Вася
2 Аня
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495482
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лунтик,

"первые" - это в порядке возрастания recno() или как-то ещё?
А если злобный хаксор Вова ночью откроет эту таблицу и воспользуется командой insert (не insert-sql, а просто insert), и получится у вас
ab1Вася1Петя1Ваня2Вова2Аня2Таня2Маня, что тогда делать?
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495503
Лунтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
tanglir,

для простоты можно считать, что таблица упорядочивается как нужно непосредственно перед выборкой.

Вообще, пытаюсь решить две задачи, в моем представлении, аналогичные по решению:
1. Выбирать первую операцию за день (период больше дня)
2. Найти первый вариант названия организации в списке строк с одинаковыми ИНН (из разных баз собирается консолидированная таблица контрагентов и получается, что для данного ИНН существует несколько вариантов реквизитов, главное чтобы они были из одной строки, т.е. поля не противоречили друг другу, например, КПП соответствовал бы адресу. Для данной задачи все равно какое значение возьмется, но ,наверно, логично, если возьмется первое)
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495542
Koryuu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Первую задачу я бы делал через seek - он находит как раз первое значение
А вот со вторым, по моему опыту, легче как раз брать последнюю запись:
Код: plaintext
1.
SET ENGINEBEHAVIOR  70 
sele * from table1 group by a into cursor outcursor

авторглавное чтобы они были из одной строки, т.е. поля не противоречили друг другу
Семь раз перечитал, чесслово. Не понял :-(
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495642
Лунтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот это да! Красивее не бывает - просто живописно!

Почему это вообще работает? Что это за SET ENGINEBEHAVIOR 70? Как Вы на это вышли?

Уважьте, Koryuu, напишите пару слов как этим пользоваться (HELP совсем невнятный).
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495665
IgorNG
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лунтик,

Включает режим совместимости SQL-заппросов для версий Visual FoxPro 7.0, 8.0, и 9.0.


SET ENGINEBEHAVIOR 70 | 80 | 90



Параметры
70


Включает режим совместимости команд SQL в системе Visual FoxPro как в версиях, ниже 8.0.
80


Определяет выполнение команд SQL для версии Visual FoxPro 8.0. в следующей таблице описаны особенности данного режима.
Опции SQL SELECT Поведение команды SELECT-SQL
DISTINCT
Вы не можете использовать опцию DISTINCT с полями типа Memo или General. Вместо этого используйте функции PADR( ) или ALLTRIM( ) для этих полей.

Дополнительно см. Функции PADL( ) | PADR( ) | PADC( ) и функция ALLTRIM( ).

UNION
Опция UNION не поддерживается для полей типа Memo без предиката ALL, включенного в команду SQL SELECT.

GROUP BY
В опции GROUP BY должно быть указано поле из списка полей оператора SELECT , для которого выполняется агрегатная функция, такая как COUNT( ). Кроме того, опция GROUP BY должна содержать поле группировки, содержащееся в опции HAVING, исключая поля из агрегатных функций.

Например, следующая команда генерирует ошибку в опции GROUP BY , потому, что поле company не указано в группировке.

Копировать код
SELECT company, country FROM Customer GROUP BY country


Вы можете включать агрегатные функции в список SELECT без указания их в опции GROUP BY.

Например, следующая команда использует COUNT( ) для поля company без указания его в опции GROUP BY .

SELECT COUNT(company), country FROM Customer GROUP BY country

HAVING
Оператор SQL SELECT может содержать опцию HAVING без ссылки на опцию GROUP BY , при этом в операторе SQL SELECT не должно быть агрегатных функций.

Например, следующая команда фильтрует запрос по заданной величине "Sweden".

Копировать код
SELECT customerid FROM customers HAVING country="Sweden"


LIKE
Оператор SQL SELECT автоматически не удаляет "хвостовые" пробелы для значений в конструкции LIKE. В предыдущей версии Visual FoxPro 7.0, в обеих переменных в конструкции LIKE, перед сравнением удалялись "хвостовые" пробелы .

Например, В следующей команде выбираются данные из таблицы, имеющей следующие значения в каждой из строк, соответственно: "1.", "12 ", и "123".

Копировать код
SELECT * FROM table1 WHERE column1 LIKE "1__"


В Visual FoxPro 7.0 и младших версиях в результате вернулась бы одна запись, со значением "123". В Visual FoxPro 8.0 в результат попадают три записи: , "1 ", "12 ", и "123".

Если начальные символы совпадают, а следующие за ним удовлетворяют "маске", и имеют фиксированную длину, то конструкция LIKE обеспечивает их включение в результат запроса, "Хвостовые" пробелы не отбрасываются


90


Определяет выполнение команд SQL в соответствие со стандартными требованиями версии Visual FoxPro 9.0 (По-умолчанию) . В следующей таблице описаны особенности применения оператора SQL SELECT.
Опции SQL SELECT Поведение команды SQL-SELECT
TOP nExpr
Когда используется данная опция: TOPnExpr[PERCENT] , команда SQL SELECT возвращает в результате не больше указанного количества записей: nExpr[PERCENT] . Дополнительно: SQL -средство в этом случае более эффективно использует доступную память и быстрее получает результат запроса, когда опция TOP указывается без ключевого слова PERCENT .

GROUP BY
Когда в запросе используется агрегатная функция, такая как MAX( ), и в команде SQL SELECT отсутствует конструкция GROUP BY , то записей в результате не будет, Visual FoxPro поместит в результат одну запись, системная переменная _TALLY будет = 1. В предыдущих версиях записей в результате не будет, _TALLY = 0.

ORDER BY
Команда SELECT … DISTINCT … ORDER BY генерирует ошибку если в опции ORDER BY указывается поле, которое отсутствует в списке полей команды SELECT .

Копировать код
CREATE CURSOR foo (f1 int, f2 int)SELECT DISTINCT f1 FROM foo ORDER BY f2 INTO CURSOR res


HAVING
Команда SELECT … DISTINCT … HAVING генерирует ошибку если в опции HAVING указано поле, отсутствующее в списке команды SELECT.

Копировать код
CREATE CURSOR foo (f1 int, f2 int)SELECT DISTINCT f1 from foo HAVING f2>1 INTO CURSOR res



Комментарии
Действие команды SET ENGINEBEHAVIOR является глобальным.

Использование установки SET ENGINEBEHAVIOR = 70 может привести к неожиданным результатам при выполнении команды SQL SELECT с опциями DISTINCT и UNION для молей типа MEMO, а также при использовании опций GROUP BY , HAVING без указания конструкции GROUP BY, а также когда используется оператор сравнения LIKE .

Когда используется установка SET ENGINEBEHAVIOR = 70 или = 80, относительно опции TOP в команде SQL SELECT в результат запроса может попасть более чем nExpr записей когда в команде также присутствует опция ORDER BY. Например, Вы задаете nExpr=10. Если в таблице имеется более чем 10 записей с одинаковым значением поля группировки, которое указано в опции ORDER BY , то в результате запроса будет больше чем 10 записей.
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495849
reware
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛунтикНапример, есть таблица
1 Вася
1 Петя
1 Ваня
2 Аня
2 Таня
2 Маня

Нужно получить
1 Вася
2 Аня
Класс вопрос !
А у меня (гипотетически) есть таблица
1 Марь Иванна
1 Дядя Федя
2 Тётя из Куйбышева
2 Брат из Магадана
И как мне красиво показать их дни рождения ? :) Чушь полная, пардон.
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495898
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лунтик2. Найти первый вариант названия организации в списке строк с одинаковыми ИНН (из разных баз собирается консолидированная таблица контрагентов и получается, что для данного ИНН существует несколько вариантов реквизитов, главное чтобы они были из одной строки, т.е. поля не противоречили друг другу, например, КПП соответствовал бы адресу. Для данной задачи все равно какое значение возьмется, но ,наверно, логично, если возьмется первое)
Я бы крайне НЕ советовал менять настройку SET ENGINEBEHAVIOR. Вы получите большие проблемы при сопровождении программы. Когда понадобиться что-то изменить.

В Вашем случае я бы пошел по пути исключения дублей еще на этапе формирования консолидированной таблицы. Т.е. просто не импортировать записи, если в общей базе уже есть запись с тем же ИНН. Значительно проще не собирать "мусор", чем потом от него избавляться.

Задача поиска одной записи из группы может быть решена "стандартным" Select-SQL только в том случае, если есть некий уникальный идентификатор записи, хотя бы в пределах группы. Физический номер записи на эту роль не годится. Впрочем, этот идентификатор можно и создать. Но все-таки, лучше просто не накапливать "мусор".

Еще раз. Не надо менять настройку SET ENGINEBEHAVIOR. Получите массу проблем в будущем.
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37495927
SSn888
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лунтик,

Красиво отобрать не получиться, из г... пулю не сделать :)

Если "как вообще отобрать"
1. Выборочка с группировкой по столбцу цифери, с полями "циферь" и "сколько записей с ней"
2. результат "присобачиваем" джойном к имеющемуся курсору, также добавляем поле-нумератор (в "промежуточном итого" имеем поля "номер", "строка", "кол-во строк с таким номером", "нумератор")
3. Нумератору даем значение "порядковое в пределах группы"
Как это все выразить в запросе или нескольких - надеюсь - объяснять не надо

В итоге получим

N Name Cnt nInGr
1 Вася 3 1
1 Петя 3 2
1 Ваня 3 3
2 Аня 4 1
2 Таня 4 2
2 Маня 4 3
2 Дуня 4 4

Из чего делаете выборку примерно по WHERE nInGr == 1
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37496379
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Менять SET ENGINEBEHAVIOR нездоровое решение.
Надежнее примерно так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select distinct N, space( 100 ) as name from MyTable into cursor result readwrite
index on N tag N
sele MyTable
scan
    if !IndexSeek(MyTable.N, .T., 'result', 'N')
       ? 'Косяк N =',MyTable.N
       loop
   endif
   if empty(result.name)
      * первая запись
      repl in result name with MyTable.Name
   else
      * Повтор, если надо сравниваем текущую запись MyTable с первым найденным (текущая запись result)
   endif
endscan
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37496680
Лунтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пробую LOOKUP(ReturnField, eSearchExpression, SearchedField [, cTagName])

не совсем понятно насчет ReturnField,SearchedField:
ReturnField:Определяет поле, содержание которого LOOKUP( ) возвращает в случае успешного поиска
SearchedField:Определяет поле, в котором осуществлять поиск

Указываю поля через алиас (ТаблицаГдеИскать.ИмяПоля) - вроде работает, указываю в качестве ReturnField RecNo() - вроде работает. Так что там можно указать: поле из текущей области или все-таки выражения да еще и из соседней области.

И по скорости что-то не очень, наверное последний совет с index on поправильнее будет.
А может установить SET ENGINEBEHAVIOR 70 непосредственно перед выборкой, а потом вернуть?
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37496758
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛунтикПробую LOOKUP(ReturnField, eSearchExpression, SearchedField [, cTagName])

И по скорости что-то не очень, наверное последний совет с index on поправильнее будет.
А может установить SET ENGINEBEHAVIOR 70 непосредственно перед выборкой, а потом вернуть?
По скорости: без использования индексов всегда медленно, т.к. каждый раз происходит перебор всех записей до нахождения нужной.

SET ENGINEBEHAVIOR - не гарантирует что попадет именно первая запись, то что обычно первая выбирается не значит что оно так всегда будет работать. Эта настройка появилась из-за того что до 7й версии у фокса был свой язык SQL, а после его привели в соответствии стандартам SQLя, а этот SET оставили чтобы старые проги могли работать без переписывания запросов.

Использовать только SELECTы для твоей задачи нельзя, т.к. в SQLе нет вообще понятия номер записи, как следствие нет первой записи. Все записи равны и их порядок определяется только правилами сортировки.
Поэтому надо использовать SCAN, если скорость критична, то можешь еще так попробовать:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create cursor result (N i, name c( 100 ))
index on N tag N
set order to
sele MyTable
scan
    if !IndexSeek(MyTable.N, .T., 'result', 'N')
      * первая запись
      insert into result (N, name) values (MyTable.N, MyTable.Name)
   else
      * Повтор, если надо сравниваем текущую запись MyTable с первым найденным (текущая запись result)
   endif
endscan
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37496939
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TSET ENGINEBEHAVIOR - не гарантирует что попадет именно первая запись, то что обычно первая выбирается не значит что оно так всегда будет работать.
По условию задачи - не имеет значения первая, последняя или откуда-то из середины. Ему надо всего-лишь, чтобы ВСЕ поля были из одной записи таблицы-источника. Не только те, которые входят в группировку. Скорее всего, ЭТО условие будет соблюдаться. Хотя, согласен, что лучше настройку SET ENGINEBEHAVIOR не трогать

Dima T Эта настройка появилась из-за того что до 7й версии у фокса был свой язык SQL, а после его привели в соответствии стандартам SQLя
Немного не так расставлены акценты. Свой язык (точнее, диалект) SQL как был в FoxPro, так и остался. Его приблизили к стандарту.

Dima TИспользовать только SELECTы для твоей задачи нельзя, т.к. в SQLе нет вообще понятия номер записи, как следствие нет первой записи. Все записи равны и их порядок определяется только правилами сортировки.
Опять не вполне точно. Да, понятия порядкового номера нет. Но есть понятие "идентификатор записи". Если такой идентификатор существует в таблице, то задача может быть решена чистым Select.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
* Предположим, имеем такую структуру данных
* Поле curId - это и есть идентификатор записи
create cursor curTest (curId i, GroupId I, FIO C( 10 ))
insert into curTest values ( 1 ,  1 , "Вася")
insert into curTest values ( 2 ,  1 , "Петя")
insert into curTest values ( 3 ,  1 , "Ваня")
insert into curTest values ( 4 ,  2 , "Аня")
insert into curTest values ( 5 ,  2 , "Таня")
insert into curTest values ( 6 ,  2 , "Маня")

* Берем "первую" запись из группы, определяя "первую" как 
* запись, имеющую минимальное значение поля curId в пределах группы
select * ;
from curTest ;
where not exists(select  1  from curTest tab2 ;
                       where tab2.GroupId = curTest.GroupId ;
                          and tab2.curId < curTest.curId)

В принципе, этот самый идентификатор можно сконструировать искусственно в самом запросе используя для этой цели либо Recno(), либо Integer-Autoincrement (через CAST()). Т.е. сделать подзапросы. Вопрос в том, насколько это будет оправдано. Может, такое поле все-таки есть в таблице?
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37496957
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На всякий случай, чтобы не было недоразумений.

В приведенном запросе использовать в качестве идентификатора, например FIO - нельзя, поскольку нет гарантий уникальности этого самого FIO в пределах группы. А использовать все поля при сравнении на больше/меньше в одном запросе - бессмысленно. Неизвестно ведь в какой комбинации будут находится значения из разных записей.

Нужен именно уникальный идентификатор записи. Primary Key. Который бы однозначно идентифицировал записи в таблице.
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37497078
P000567
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
- Привет?
- Привет.
Как звали того грузина котоый утопил в колодце гвозди?

.... 30 часов молчания.

P/S: Заржавелли.

Вот вопрос такой. Ответ будет такой же.
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37497219
Лунтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ ,

это то, что надо. У Вас всегда в заначке что-нибудь нужное. СПАСИБО!
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37498806
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
для простоты можно считать, что таблица упорядочивается как нужно непосредственно перед выборкой.

вообще не понятно из-за чего шум
первым запросом в курсор выбираем по ключевым минимальную фамилию
потом левое соединение

иначе говоря операция в два действия
1. создаем курсор отбора
2. отбираем записи по условию
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37498812
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
exists ладно ...
но not exists в фоксе это граната в руках обезьяны
левое соединение быстрее
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37498898
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sWinTyzвообще не понятно из-за чего шум
первым запросом в курсор выбираем по ключевым минимальную фамилию
потом левое соединение

иначе говоря операция в два действия
1. создаем курсор отбора
2. отбираем записи по условию
Теперь представим, что есть две записи с одинаковыми фамилиями. А если есть дубли в других полях? В общем случае, Вам придется повторить описанный цикл для КАЖДОГО поля записи.

Кроме того, а при чем здесь именно левое объединение? Вы вообще в курсе для чего оно предназначено?

sWinTyzexists ладно ...
но not exists в фоксе это граната в руках обезьяны
левое соединение быстрее
Во-первых, для FoxPro, в общем случае , LEFT JOIN - не быстрее чем NOT EXISTS или NOT IN. Скорость выполнения будет примерно одинакова.

Во-вторых, NOT EXISTS - вполне естесственно "переводится" на "человеческий" язык. Буквально. Здесь нет неоднозначности. "Не существует". Чего здесь непонятного-то?

А вот LEFT JOIN практически все новички интерпретируют не адекватно. Постоянно справшивают, почему результат получается не такой, как вроде бы должен быть, если перевести как "присоединить к левой таблице" (а новички именно ТАК и "переводят"). А подобный перевод именно и вводит в заблуждение. Судя по Вашему предыдущему посту, Вы тоже не вполне понимаете для чего оно используется.

Другими словами, если есть выбор между NOT EXISTS и LEFT JOIN, то используя NOT EXISTS меньше вероятность получить неожиданный (не ожидАемый) результат, чем при использовании LEFT JOIN
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499028
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. фамилии то может быть и две
а группировочное поле одно
да и минимум один

2. насчет NOT EXISTS даже не знаю что сказать ....
я думал это я читал рекомендации Базеяна
черная толстая книга если помните
но видимо память меня сдает
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499045
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати полученный курсор
насколько я помню можно использовать в опции IN ()
там вроде через запятую можно поля указать ?
ну если нельзя тогда пожно собрать строку
но это будет дольше

так что способов явно больше чем два

а вообще не знаю
я от фокса отшел
человеку который так долго сидит на фоксе конечно виднее
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499049
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sWinTyz1. фамилии то может быть и две
а группировочное поле одно
да и минимум один
Вы точно понимаете о чем говорите?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
create cursor test (f1 I, f2 C( 10 ))
insert into test values ( 1 , 'one')
insert into test values ( 1 , 'one')
insert into test values ( 2 , 'two')

select f1, min(f2) as f2 from test into cursor curGroup nofilter group by f1

* Вот Ваше левое объединение, дающее "парадоксальный" результат
select test.* ;
from test ;
left join curGroup on test.f1 = curGroup.f1 and test.f2 = curGroup.f2

Или как Вы себе представляете второй запрос?
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499063
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вообще Вы правы
что там крутили с recno() на фоксе
в старых таблицах нет ИД но рекномер есть
за три запроса можно сделать это
но все это как то не быстро
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499081
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
эх ... коротка кольчужка ...

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
create cursor test (f1 I, f2 C( 10 ))
insert into test values ( 1 , 'one')
insert into test values ( 1 , 'one')
insert into test values ( 2 , 'two')

select *,str(recno()) as nn from test into cursor c1 nofilter

select f1, min(f2+nn) as f2 from c1 into cursor curGroup group by f1

select test.* from c1  where nn in (Select substr(nn, 11 ))
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499082
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
create cursor test (f1 I, f2 C( 10 ))
insert into test values ( 1 , 'one')
insert into test values ( 1 , 'one')
insert into test values ( 2 , 'two')

select *,str(recno()) as nn from test into cursor c1 nofilter

select f1, min(f2+nn) as f2 from c1 into cursor curGroup group by f1

select c1.* from c1  where nn in (Select substr(nn, 11 ) from curGroup)
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499096
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
можно и одним
но фокс вроде тяжко переваривает трехэтажные запросы
не уверен что сделает селек из селект
плохо работает с рекно()
да и груп бай в опции ин может ругаться этого я точно не помню
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499304
reware
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я тут поигрался с данным вопросом, включив в него пару своих функций. Ничего толкового не вышло. Идея была сохранять в массиве номера id обработанных записей. Работает, но криво через SQL-SELECT. Там, видимо, ещё и внутри селекта такая дребедень, которой лучше не касаться. Пришёл к выводу, что это проще делать обычным процедурным способом. Индексирование (по UNIQUE ?), выбор, запись куда-нить. Селект он хорош, однакож "о сколько нам открытий чудных готовит..." :)
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37499658
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sWinTyzможно и одним
но фокс вроде тяжко переваривает трехэтажные запросы
не уверен что сделает селек из селект
плохо работает с рекно()
да и груп бай в опции ин может ругаться этого я точно не помню
Для начал, если Вы создали уникальный идентификатор, то зачем все остальные "пляски с бубном" по объединению с дополнительным полем? Чем Вас не устравает минимальное значение самого уникального идентификатора? Он на то и уникален.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create cursor test (f1 I, f2 C( 10 ))
insert into test values ( 1 , 'one')
insert into test values ( 1 , 'one')
insert into test values ( 2 , 'two')

select *,recno() as nn from test into cursor c1 nofilter

select f1, min(nn) as nn from c1 into cursor curGroup group by f1

select * from c1  where nn in (Select nn from curGroup)

Следующий вопрос. А почему Вы решили что в таблице нет уникального идентификатора? Потому что его не было в исходной постановке? Так вроде автора вопроса мое решение основанное как раз на существовании уникального идентификатора вполне устроило. Т.е. идентификатор все-таки есть.

Наконец, подзапросы в VFP9 делать уже можно. В старых версиях действительно нельзя было. В данном случае, можно пропустить вторую выборку

Код: plaintext
select * from c1  where nn in (select min(nn) as nn from c1 group by f1)

Только опять же, а зачем?
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37500129
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2ВладимирМ
да ладно бог с ним ... давно я шашки в руках не держал
еще с гражданской
спасибо за полученное удовольствие

а можно вопрос ?
чем сейчас такой маститый фокспрошник занимается?
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37500138
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
кстати мои последние запросы несколько отличаются от последнего поста Вашего
ну да не важно
желание спорить совсем нет
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37500172
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
Чем Вас не устравает минимальное значение самого уникального идентификатора? Он на то и уникален.


ну вот как то не устраивает
даже сам не пойму почему, привычка наверное
ищу именно первую запись по индексу, а потом уже обеспечиваю уникальность
, а не просто беру первую по порядку следования записей в таблице в приделах группировки
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37500225
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Засомневался насчет скорости предложенных вариантов, решил померить.
Исходники тутclear
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
if !file('test.dbf')
	create Table (lcFile) free (nId i autoinc, nNom i, cText c( 10 ))
	for i =  1  to  10000000 
		insert into test (nNom, cText) values (rand() *  9999  +  1 , sys( 2015 ))
	endfor
	index on nId tag nId
	index on nNom tag nNom
	index on bintoc(nNom) + bintoc(nId) tag NomId collate "machine"
	use in test
else
	if used('test')
		use in test
	endif
endif

sele  0 
use test shared
Test1()
Test1()
Test1()
Test2()
Test2()
Test2()
*!*	Test3()
*!*	Test3()
*!*	Test3()
Test4()
Test4()
Test4()

return

func Test1
if used('Res1')
	use in Res1
endif
lnSec = Seconds()
select * ;
from Test ;
where not exists(select  1  from Test tab2 ;
                       where tab2.nNom = Test.nNom;
                          and tab2.nId < Test.nId);
	into cursor Res1
? 'Test1', Seconds() - lnSec
return                      

func Test2
if used('Res2')
	use in Res2
endif
lnSec = Seconds()
create cursor res2 (nId i, nNom i, cText c( 10 ))
index on nNom tag nNom
set order to
sele Test
scan
    if !IndexSeek(Test.nNom, .T., 'res2', 'nNom')
      insert into res2 (nId, nNom, cText) values (Test.nId, Test.nNom, test.cText)
   endif
endscan
? 'Test2', Seconds() - lnSec
return                      

func Test3
if used('Res3')
	use in Res3
endif
lnSec = Seconds()
create cursor res3 (nId i, nNom i, cText c( 10 ))
sele Test
set Order To NOMID   && BINTOC(NNOM)+BINTOC(NID) 
scan
    if Test.nNom != res3.nNom
      insert into res3 (nId, nNom, cText) values (Test.nId, Test.nNom, test.cText)
   endif
endscan
? 'Test3', Seconds() - lnSec
return                      

func Test4
if used('Res4')
	use in Res4
endif
lnSec = Seconds()
*select *,recno() as nn from test into cursor c1 nofilter
select nNom, min(nId) as nn from Test into cursor curGroup group by nNom
select * from c1  where nn in (Select nn from curGroup) into cursor res4
? 'Test4', Seconds() - lnSec
return   

У меня результаты такие:
Test1 (select ... where not exists) - 98 сек среднее (тут большие разбеги по времени 74, 106 и 118, непонятно отчего замедление)
Test2 (SCAN без индекса) - 17,5 сек
Test3 (SCAN c индексом) - 212 сек
Test4 (два селекта) - 15,8 сек

В итого при наличии ID выигрывает вариант предложенный sWinTyz, при отсутствии ID - он дольше (22 сек) чем мой вариант со сканом. Очень удивила скорость скана при включенном индексе, не думал что настолько медленнее будет.
...
Рейтинг: 0 / 0
Как красиво отобрать первые встретившиеся записи?
    #37500327
sWinTyz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
опыт не пропьешь ....

замечание :
тут еще важен порядок исполнения методов
если это все происходило в одной процедуре конечно
фокс работает то ли со стеком памяти то ли еще с чем то
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как красиво отобрать первые встретившиеся записи?
    #38180419
USE ..
INDEX ON id TO tst UNIQUE
BROWSE
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как красиво отобрать первые встретившиеся записи?
    #39048915
chyber
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Предположительно, если первый столбец был уникальным ключом recno,
select field1,field2 from table group by field1,field2(?) having recno=min(recno)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как красиво отобрать первые встретившиеся записи?
    #39898773
Лунтик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ, дайте еще раз спасибо скажу) еще раз пригодилось ...
...
Рейтинг: 0 / 0
36 сообщений из 36, показаны все 2 страниц
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Как красиво отобрать первые встретившиеся записи?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]