powered by simpleCommunicator - 2.0.56     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / выборка последнего движения
31 сообщений из 31, показаны все 2 страниц
выборка последнего движения
    #35739319
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть 2 таблицы справочник сотрудников K1 и движения сотрудников K2, хочется получить список сотрудников с данними только последнего движения.
собственно в фоксе я бы назначить отношение по обратному индексу даты движения и scan по справочнику - набрал бы нужные данные.
однако хочется сделать select-sql
казалось бы:
Код: plaintext
1.
SELECT k2_temp.postn, fam,im, otch, k2_temp.cex, k2_temp.tabn  FROM k1 ;
INNER JOIN (SELECT cex, tabn FROM k2 TOP  1  ORDER BY dper DESC) as k2_temp ON k2_temp.postn = k1.postn
ан нет - говорит синтаксическая ошибка.
подскажите пожалуйста как бы сделать такую выборку?
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739349
АлексейОЕсть 2 таблицы справочник сотрудников K1 и движения сотрудников K2, хочется получить список сотрудников с данними только последнего движения.
собственно в фоксе я бы назначить отношение по обратному индексу даты движения и scan по справочнику - набрал бы нужные данные.
однако хочется сделать select-sql
казалось бы:
Код: plaintext
1.
SELECT k2_temp.postn, fam,im, otch, k2_temp.cex, k2_temp.tabn  FROM k1 ;
INNER JOIN (SELECT cex, tabn FROM k2 TOP  1  ORDER BY dper DESC) as k2_temp ON k2_temp.postn = k1.postn
ан нет - говорит синтаксическая ошибка.
подскажите пожалуйста как бы сделать такую выборку?
Top обычно идет сразу за словом select, а не где-то там в конце запроса.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739354
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОЕсть 2 таблицы справочник сотрудников K1 и движения сотрудников K2, хочется получить список сотрудников с данними только последнего движения.
собственно в фоксе я бы назначить отношение по обратному индексу даты движения и scan по справочнику - набрал бы нужные данные.
однако хочется сделать select-sql
казалось бы:
Код: plaintext
1.
SELECT k2_temp.postn, fam,im, otch, k2_temp.cex, k2_temp.tabn  FROM k1 ;
INNER JOIN (SELECT cex, tabn FROM k2 TOP  1  ORDER BY dper DESC) as k2_temp ON k2_temp.postn = k1.postn
ан нет - говорит синтаксическая ошибка.
подскажите пожалуйста как бы сделать такую выборку?
А где вы такой синтаксис про TOP нашли?
Может так:
Код: plaintext
1.
SELECT k2_temp.postn, fam,im, otch, k2_temp.cex, k2_temp.tabn  FROM k1 ;
INNER JOIN (SELECT TOP  1  cex, tabn FROM k2 ORDER BY dper DESC) as k2_temp ON k2_temp.postn = k1.postn
С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739355
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
проходящий.Top обычно идет сразу за словом select, а не где-то там в конце запроса. перестановка не помогла - ошибка таже
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739362
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
select в скобках отдельно исполняется удачно и с нужними данными
Код: plaintext
SELECT TOP  1  cex, tabn FROM k2 ORDER BY dper DESC WHERE k2.postn = k1.postn
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739363
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОпроходящий.Top обычно идет сразу за словом select, а не где-то там в конце запроса. перестановка не помогла - ошибка таже
У вас в подзапросе нет поля postn, а вы его перечисляете как результат!
Код: plaintext
1.
2.
SELECT k2_temp.postn, fam,im, otch, k2_temp.cex, k2_temp.tabn  FROM k1 ;
INNER JOIN (SELECT TOP  1  cex, tabn, postn FROM k2 ORDER BY dper DESC) as k2_temp ON k2_temp.postn = k1.postn
С уважением, Алексей.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739368
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksey-K,
ну не помогает эта перестановка
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739381
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksey-KУ вас в подзапросе нет поля postn, а вы его перечисляете как результат!
Код: plaintext
1.
2.
SELECT k2_temp.postn, fam,im, otch, k2_temp.cex, k2_temp.tabn  FROM k1 ;
INNER JOIN (SELECT TOP  1  cex, tabn, postn FROM k2 ORDER BY dper DESC) as k2_temp ON k2_temp.postn = k1.postn

поправил - syntax error.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739384
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
добавлю что VFP 8 , полагаю что не принципиально.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739385
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейО, а версия VFP у вас какая ?
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739392
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОдобавлю что VFP 8 , полагаю что не принципиально.
Ничего себе не принципиально!
Только в VFP 9.0 появились TOP n в корреляционных подзапросах:
Вот цитата из HELP

Что нового в SELECT-SQL VFP 9.0:

TOP N in a Non-Correlated Subquery
Visual FoxPro 9.0 supports the TOP N clause in a non-correlated subquery. The ORDER BY clause should be present if the TOP N clause is used, and this is the only case where it is allowed in subquery.

The following is the general syntax for the TOP N clause in a non-correlated subquery.

SELECT … WHERE … (SELECT TOP nExpr [PERCENT] … FROM … ORDER BY …) …

С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739401
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поправляю себя - в некорреляционных подзапросах.
Как раз ваш случай.
Переходите на VFP 9.0 или через временный курсор.
С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739466
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksey-K,
Да . действительно. в 9ке синтакс прошел. однако получил не ту информацию что ожидал - разбираюсь...
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739554
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
АлексейО,

получается что подзапрос выполняется 1 раз а не на каждой иттерации основного запроса как ожидал я.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739566
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОAleksey-K,
Да . действительно. в 9ке синтакс прошел. однако получил не ту информацию что ожидал - разбираюсь...
И не должны были получить :)
Внутренний запрос выбирает TOP 1 из всех postn!
Может так получится:
Код: plaintext
1.
2.
3.
4.
SELECT k1.postn, k1.fam, k1.im,  k1.otch, k2_temp.cex, k2_temp.tabn  ;
FROM k1 INNER JOIN (SELECT k2.postn, k2.cex, k2.tabn FROM k2 ;
WHERE k2.dper = (SELECT MAX(kx.dper) FROM k2 kx ON k2.postn = kx.postn)) ;
AS k2_temp ON k2_temp.postn = k1.postn
С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739579
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОАлексейО,

получается что подзапрос выполняется 1 раз а не на каждой иттерации основного запроса как ожидал я.
Тогда вам нужен внутренний корреляционный подзапрос.
А он с TOP n и в VFP 9.0 не работает.
С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739675
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вместо решения "в лоб" через TOP 1 надо просто объединить таблицы и добавить исключение записей с датой, для которых существует бОльшая дата

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT 
    k2.postn, ;
    k1.fam, ;
    k1.im, ;
    k1.otch, ;
    k2.cex, ;
    k2.tabn  ;
FROM k1 ;
INNER JOIN k2 ON k2.postn = k1.postn ;
WHERE NOT EXISTS(select 'x' from k2 as k2_exist ;
                            where k2_exist.postn = k2.postn and k2_exist.dper > k2.dper)

Разумеется, это имеет смысл, если нет дублей по дате. Точнее, нет двух записей с максимальной датой.

Правда, не уверен, что такой запрос синтаксически корректен для VFP8.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739681
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksey-KМожет так получится:
Код: plaintext
1.
2.
3.
4.
SELECT k1.postn, k1.fam, k1.im,  k1.otch, k2_temp.cex, k2_temp.tabn  ;
FROM k1 INNER JOIN (SELECT k2.postn, k2.cex, k2.tabn FROM k2 ;
WHERE k2.dper = (SELECT MAX(kx.dper) FROM k2 kx ON k2.postn = kx.postn)) ;
AS k2_temp ON k2_temp.postn = k1.postn

да. цель достигнута.
но впрочем я ей достигал за 2 select-a и за меньшее время.
я то надеялся что написав в одном я сокращю время.
и практически уверен что scan выполнит это еще быстрее
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739700
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМВместо решения "в лоб" через TOP 1 надо просто объединить таблицы и добавить исключение записей с датой, для которых существует бОльшая дата
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
SELECT 
    k2.postn, ;
    k1.fam, ;
    k1.im, ;
    k1.otch, ;
    k2.cex, ;
    k2.tabn  ;
FROM k1 ;
INNER JOIN k2 ON k2.postn = k1.postn ;
WHERE NOT EXISTS(select 'x' from k2 as k2_exist ;
                            where k2_exist.postn = k2.postn and k2_exist.dper > k2.dper)

да. спасибо. это тоже работает, но практически за такое же время.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739701
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОAleksey-KМожет так получится:
Код: plaintext
1.
2.
3.
4.
SELECT k1.postn, k1.fam, k1.im,  k1.otch, k2_temp.cex, k2_temp.tabn  ;
FROM k1 INNER JOIN (SELECT k2.postn, k2.cex, k2.tabn FROM k2 ;
WHERE k2.dper = (SELECT MAX(kx.dper) FROM k2 kx ON k2.postn = kx.postn)) ;
AS k2_temp ON k2_temp.postn = k1.postn

да. цель достигнута.
но впрочем я ей достигал за 2 select-a и за меньшее время.
я то надеялся что написав в одном я сокращю время.
и практически уверен что scan выполнит это еще быстрее
Все зависит от наличия подходящих индексов. Например, по postn во всех таблицах и по dper в k2
С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739715
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksey-KВсе зависит от наличия подходящих индексов. Например, по postn во всех таблицах и по dper в k2 да. эти индексы есть и 40 т. записей обрабатывает за 13-14 секунд, но этого мне мало.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739750
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОAleksey-KВсе зависит от наличия подходящих индексов. Например, по postn во всех таблицах и по dper в k2 да. эти индексы есть и 40 т. записей обрабатывает за 13-14 секунд, но этого мне мало.
Для отчета - вполне нормальное время. Пользователь воспримет такую задержку при выполнении отчета с пониманием и не будет "дергаться".

А для текущей работы нет смысла отбирать 40 тысяч записей. Ни один пользователь не в состоянии "охватить" такой объем информации. Т.е. отбираемую информацию надо ограничить какими-либо дополнительными условиями. Например, движения сотрудников за последний месяц.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739774
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ,
да мне надо для оперативной работы и я могбы отобрать по условию первой таблицы, но это дает сокращение только на десятые, а фильтры по второй таблице невозможны (вдруг там нет движений за последний месяц, а сведения нужны)
впрочем, всем СПАСИБО. а получил ответ.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739809
Фотография Aleksey-K
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейО, Все понятно...
Но если движения может и не быть, я бы переделал INNER JOIN на LEFT JOIN и заменил бы k2_temp.cex и k2_temp.tabn на NVL(k2_temp.cex, 0) AS cex и NVL(k2_temp.tabn, 0) AS tabn соответственно (если они цифровые, иначе на пустую строку). Итого:
Код: plaintext
1.
2.
3.
4.
SELECT k1.postn, k1.fam, k1.im,  k1.otch, NVL(k2_temp.cex,  0 )  AS cex, NVL(k2_temp.tabn,  0 ) AS tabn ;
FROM k1 LEFT JOIN (SELECT k2.postn, k2.cex, k2.tabn FROM k2 ;
WHERE k2.dper = (SELECT MAX(kx.dper) FROM k2 kx ON k2.postn = kx.postn)) ;
AS k2_temp ON k2_temp.postn = k1.postn
Но все-таки оставил бы SELECT-SQL, а не SCAN...ENDSCAN
Вдруг, будете перводить свое приложение на клиент-сервер. Проще будет эту операцию выполнить, если как можно больше в ANSI-SQL.
С уважением, Алексей
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739822
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Aleksey-KНо если движения может и не быть, хоть одно движение есть, просто неизвестно когда оно, может человек устроился на завод 20 лет назад и простоял перед одним станком
Aleksey-KВдруг, будете перводить свое приложение на клиент-сервер. Проще будет эту операцию выполнить, если как можно больше в ANSI-SQL.
именно так я и рассуждал, но ... 4 секунды против 13-ти ... я выбрал scan.
СПАСИБО за помощь.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739905
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОно ... 4 секунды против 13-ти ... я выбрал scan.
SCAN-то зачем? Если стоит задача отображения в Grid, то можно использовать SET RELATION. Без дополнительного SET SKIP TO получится связь один-к-одному.

Дело в том, что в FoxPro можно настроить связь по частичному совпадению ключа. По первым символам. Надо только "сконструировать" специфический индекс.

Итак, основная связь осуществляется по значению поля postn, но в пределах одного и того же значения поля postn надо упорядочить записи по убыванию значения поля dper. Т.е. первой должна быть запись с максимальным значением dper.

Если dper - это дата, то проще "перевести" ее в число. Поскольку разница двух перменных типа Date - это количество дней, то если вычесть dper из некоторой, заведомо большой даты, то и получим упорядочивание по убыванию. Затем переводим полученное число в строку.

Если поле postn типа Integer, то получаем такое выражение индекса

Код: plaintext
1.
2.
select k2
INDEX ON  BINTOC(postn) + BINTOC({^ 2100 - 01 - 01 } - dper)

Теперь остается настроить связь

Код: plaintext
1.
2.
select k1
SET RELATION TO BintoC(postn) INTO k2

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

SET EXACT OFF

Но, поскольку это настройка по умолчанию, то проблем быть не должно.

Функция BINTOC() использована для уменьшения длины ключа. Для перевода в символьное представление можно использовать и STR(). Но, поскольку в данном случае, удалять ведущие пробелы нельзя, то ключ получится больше по размеру. А значит, бОльшего размера будет индексный файл.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35739922
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМФункция BINTOC() использована для уменьшения длины ключа.
Добавлю что BINTOC() нельзя использовать при SET COLLATE "RUSSIAN", только при "MACHINE"
...
Рейтинг: 0 / 0
выборка последнего движения
    #35740048
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМSCAN-то зачем? :-)
ну это я образно сказал.
конечно именно так и сделано : индекс чтобы нужная запись была сверху, отношение во вторую таблицу, и даже не scan а replace all
...
Рейтинг: 0 / 0
выборка последнего движения
    #35740078
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АлексейОВладимирМSCAN-то зачем? :-)
ну это я образно сказал.
конечно именно так и сделано : индекс чтобы нужная запись была сверху, отношение во вторую таблицу, и даже не scan а replace all
Все-равно не понятно. Зачем выполнять модификацию? Разве факта настроенной связи недостаточно? Почему нельзя отобразить информацию напрямую из связанной таблицы без "перекачки" по REPLACE?

Если же нужна именно модификация, то почему нельзя наложить фильтр (не все же записи модифицируются), чтобы ограничить изменяемые записи и уйти от сканирования всей таблицы?

Собственно, что необходимо сделать-то? Какова решаемая задача, а не выбранный способ решения? Для чего изначально планировался запрос, описанный в начале темы? Что с этой выборкой потом происходило?
...
Рейтинг: 0 / 0
выборка последнего движения
    #35740159
АлексейО
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМ, я прекрасно понимаю где в моем решении неоптимальности, но они обусловлены неким глобальным решением. впрочем мы это с Вами обсуждали здесь
повторюсь, что для целей высокой скорости разработки прикладных приложений я стараюсь реализовывать многое не столько с точки зрения оптимальности под конкретный случай а с точки зрения "черных ящиков" под многие случаи. и поэтому в данном случае эта выборка: курсор по которому пользователь хочет выбирать этих сотрудников используя как фильтры, частичные поиски так и "поиски глазами". а для прикладного программиста это выглядит как обычная таблица - ну просто для быстроты разработки программистом невысокой квалификации.
еще один довод: когда всетаки дело дойдет до SQL то переписать выборку на select будет всетаки проще чем искоренять файл-серверные решения из прикладной программы.
...
Рейтинг: 0 / 0
выборка последнего движения
    #35740340
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, дело хозяйское.

Хотя должен заметить, что приложение, изначально написанное как файл-серверное, просто так перевести в клиент-серверное не получится. И термин "проще" здесь не уместен. Это принципиально другая идеология построения приложения.

Поэтому, писать файл-серверное приложение исходя из предположения, что когда-нибудь в будущем оно будет переписано на клиент-серверное и поэтому следует писать вот так, а не так - не имеет смысла. Переписано будет ВСЕ! Весь модуль работы с данными. Не факт, что и интерфейс останется неизменным.

Простой довод: в клиент-серверном приложении никто не будет тащить на клиента 40 тысяч записей. Это слишком долго.

Значит, все ваши рассуждения о пользе SQL в данном случае теряют смысл. Не будет в клиент-серверной технолгии подобного решения в принципе. Задача будет решена другими способами. Принципиально другими.

Кроме того, "универсальные" решения хороши в теории. На практике все-таки реализуют "коллекции" частных решений. Иерархии классов. Поэтому, опять же, решать задачу "в общем случае", исходя из предположения, что частное решение можно будет приспособить и для решения других задач особого смысла не имеет.
...
Рейтинг: 0 / 0
31 сообщений из 31, показаны все 2 страниц
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / выборка последнего движения
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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