Добрый день. есть вот такой пример запроса.

Изображение удалено.

идея в том чтоб взять записи которые созданы после определенного времени.

в результате он генерирует следующий SQL запрос который не совсем подходит, так как он возвращает запись которая была возвращена в прошлой выборке (я вытаскиваю данные по 10 записей).

Изображение удалено.

пример запроса, который создается

SELECT
       "Contact"."Name" "Name",
       "Contact"."QSoftGSTime" "QSoftGSTime",
       "Contact"."ContactPhoto" "ContactPhoto",
       "Contact"."Phone" "Phone",
       "Contact"."CreatedOn" "CreatedOn",
       COALESCE("SysCityLcz"."Name", "City"."Name") "City.Name"
FROM
       "public"."Contact" "Contact"
       LEFT OUTER JOIN "public"."City" "City" ON ("City"."Id" = "Contact"."CityId")
       LEFT OUTER JOIN "public"."SysCityLcz" "SysCityLcz" ON ("SysCityLcz"."RecordId" = "City"."Id"
       AND "SysCityLcz"."SysCultureId" = '{F0EA9715-8757-474C-AEE9-743D672E48C9}')
WHERE
       "Contact"."CreatedOn" > TO_TIMESTAMP('2023-02-06 21:21:02.149', 'YYYY-MM-DD HH24:MI:SS.FF3')
ORDER BY
       "CreatedOn" ASC NULLS FIRST
LIMIT 10

получается что при выборке данных проверяется только первые три цифры из милисекунд ('2023-02-06 21:21:02.149', 'YYYY-MM-DD HH24:MI:SS.FF3'). в итоге я получаю два раза одну и ту же запись. решение это указывать все 6 цифр милисекунд следующий запрос выполняется корректно и не приводит к дублированию данных

SELECT
       "Contact"."Name" "Name",
       "Contact"."QSoftGSTime" "QSoftGSTime",
       "Contact"."ContactPhoto" "ContactPhoto",
       "Contact"."Phone" "Phone",
       "Contact"."CreatedOn" "CreatedOn",
       COALESCE("SysCityLcz"."Name", "City"."Name") "City.Name"
FROM
       "public"."Contact" "Contact"
       LEFT OUTER JOIN "public"."City" "City" ON ("City"."Id" = "Contact"."CityId")
       LEFT OUTER JOIN "public"."SysCityLcz" "SysCityLcz" ON ("SysCityLcz"."RecordId" = "City"."Id"
       AND "SysCityLcz"."SysCultureId" = '{F0EA9715-8757-474C-AEE9-743D672E48C9}')
WHERE
       "Contact"."CreatedOn" > TO_TIMESTAMP('2023-02-06 21:21:02.149528', 'YYYY-MM-DD HH24:MI:SS.FF6')
ORDER BY
       "CreatedOn" ASC NULLS FIRST
LIMIT 10

я не нашел способа управлять количеством цифр милисекунд в запросе.

можете подсказать как это правильно сделать?

пока что как хак я решил генерировать запрос с помощью EntitySchemaQuery, делать esqResult.GetSelectQuery(_connection), с него получать текст запроса и в нем уже подменять значения с помощью регулярки. но это выглядит костылем, который не хотелось бы оставлять.

 

спасибо!

 

 

 

 

Нравится

4 комментария

добавлю, что когда пробовал делать через new Select(connection), то такой проблемы не было, но тогда надо вручную управлять локализацией и делать джоины, чего не хотелось бы делать.

так же регулярное выражение может не работать для других типов БД. в данный момент используется PostgreSql

Добрый день,

 

К сожалению пока возможности управления этим количеством символов нет. Поэтому нужно подумать над альтернативными решениями обхода проблемы - возможно увеличить лимит с 10 записей на большее количество, чтобминимизировать риск ошибки, можно попробовать еще модифицировать фильтр. Возможно поможет добавление сортировки по Id - это сделает порядок записей всегда одинаковым, или просто использовать встроенную постраничность.

а можете подсказать как работать с встроенным механизмом постраничной обработки? пример или ссылка на статью. спасибо!

Показать все комментарии

Добрый день!
В модуле на js требуется запрограммировать такой запрос:

SELECT a.id
FROM Contact a
WHERE a.id > :contactId
AND EXISTS (SELECT id FROM Contact b
        WHERE
        b.id = :contactId AND
        ( (b.DebtorLastName > '' AND a.DebtorLastName = b.DebtorLastName)
        OR (b.BirthDate IS NOT NULL AND a.BirthDate = b.BirthDate)
        OR (b.Phone > '' AND a.Phone = b.Phone)
        OR (b.MobilePhone > '' AND a.MobilePhone = b.MobilePhone)
        OR (b.MobilePhone2 > '' AND a.MobilePhone2 = b.MobilePhone2))
)

часть до exists понятна, а далее не получается...

var select = Ext.create('Terrasoft.EntitySchemaQuery', { rootSchemaName: 'Contact' });
select.addColumn('Id');
select.filters.add('IdFilter', Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, 'Id', contactId));

версия BPM 7.2.0.1223

Нравится

6 комментариев

Спасибо за Ваше обращение. Мы зарегистрировали его в Службе технической поддержки и назначили специалиста, который сможет Вас компетентно проконсультировать по данному вопросу

Здравствуйте, Лариса!
Вот небольшой пример:

var esq = Ext.create('Terrasoft.EntitySchemaQuery', {
                    rootSchemaName: "Contact"
                });
				esq.addColumn('Id');
                esq.addColumn('Name');
                esq.addColumn('Account');
				var f = esq.createExistsFilter('[Activity:Contact].Id');
				var subf = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.NOT_EQUAL, 'Title', 'Test');
				f.subFilters.add('subtitleFilter', subf);
				esq.filters.add('existActivityFilter',f);

В результате формируется следующий запрос:

SELECT
	[Contact].[Id] [Id],
	[Contact].[Name] [Name],
	[Contact].[AccountId] [AccountId],
	[Account].[Name] [Account.Name],
	[Contact].[PhotoId] [PhotoId],
	[Photo].[Name] [Photo.Name]
FROM
	[dbo].[Contact] [Contact]
	LEFT OUTER JOIN [dbo].[Account] [Account] ON ([Account].[Id] = [Contact].[AccountId])
	LEFT OUTER JOIN [dbo].[SysImage] [Photo] ON ([Photo].[Id] = [Contact].[PhotoId])
WHERE
	EXISTS (
SELECT
	[SubActivity].[Id] [Id]
FROM
	[dbo].[Activity] [SubActivity]
WHERE
	[SubActivity].[ContactId] = [Contact].[Id]
	AND [SubActivity].[Title] <> 'Test')

Андрей у Вас в примере условие exists строится так (такой пример я находила):

WHERE
        [SubActivity].[ContactId] = [Contact].[Id]

а мне связывать напрямую главную таблицу и таблицу подзапроса не нужно

        WHERE 
        b.id = :contactId --тут у меня параметр

также мне не понятно как стоить остальные условия

        ( (b.DebtorLastName <> '' AND a.DebtorLastName = b.DebtorLastName)
        OR (b.BirthDate IS NOT NULL AND a.BirthDate = b.BirthDate)
        OR (b.Phone <> '' AND a.Phone = b.Phone)
        OR (b.MobilePhone <> '' AND a.MobilePhone = b.MobilePhone)
        OR (b.MobilePhone2 <> '' AND a.MobilePhone2 = b.MobilePhone2))

сам запрос можно переписать, например, так:

select a.* from Contact a 
	inner join Contact b on a.Id <> b.Id
where b.id = 'BF66B334-91DC-4E44-8587-4A0620BBC536'
and (
	(a.DebtorLastName <> '' and a.DebtorLastName = b.DebtorLastName)
	or (a.BirthDate is not null and a.BirthDate = b.BirthDate)
	or (a.Phone <> '' and a.Phone = b.Phone)
	or (a.MobilePhone <> '' and a.MobilePhone = b.MobilePhone)
	or (a.MobilePhone2 <> '' and a.MobilePhone2 = b.MobilePhone2)
)

но с точки зрения bpm мне предоставленный вариант показался самым простым...

Лариса, в таком случае можно с помощью отдельных запросов. Так будет проще, думаю.
В запросе ж сравниваются данные по одной записи по сути. Можно сначала получить запись по параметру:

esq.getEntity(contactId, function(result) {...

и в callback-функции выполнять следующий запрос с фильтрами из значений в полученной записи.
Надеюсь, понятно объяснил.

Андрей, запрос выбирает дубли контакта по определенным условиям.
Насчет двух запросов идея понятна, но Вы не ответили по поводу того как сделать такой блок условий:

        WHERE 
        b.id = :contactId AND
        ( (b.DebtorLastName <> '' AND a.DebtorLastName = b.DebtorLastName)
        OR (b.BirthDate IS NOT NULL AND a.BirthDate = b.BirthDate)
        OR (b.Phone <> '' AND a.Phone = b.Phone)
        OR (b.MobilePhone <> '' AND a.MobilePhone = b.MobilePhone)
        OR (b.MobilePhone2 <> '' AND a.MobilePhone2 = b.MobilePhone2) )

Лариса, значит не до конца идею поняли) Или я Вашу. После получения записи по параметру, то есть контакта b в Вашем запросе должно быть что-то вроде:

//...
esq.getEntity(contactId, function (response) {
    if (response.success) {
        var entity = response.entity;
        if (entity) {
            var filterGroup = Terrasoft.createFilterGroup();
            filtersGroup.logicalOperation = Terrasoft.LogicalOperatorType.OR;
            var mobilePhone = entity.get('MobilePhone');
            if (mobilePhone) {
                var mobileFilter = Terrasoft.createColumnFilterWithParameter(
                    Terrasoft.ComparisonType.EQUAL, 'MobilePhone', mobilePhone);
                filtersGroup.add('mobileFilter', mobileFilter);
            }
            //...добавление других фильтров в группу по такому же принципу
            var esqConnectedContact = Ext.create('Terrasoft.EntitySchemaQuery', {
                rootSchemaName: "Contact"
            });
            esqConnectedContact.addColumn('Id');
            esqConnectedContact.filters.add(filtersGroup);
            esqConnectedContact.getEntityCollection(function (result) {
                //callback
            }, this);
        }
    }
}, this);
//...
Показать все комментарии