Коллеги, приветствую.

Есть некоторый запрос, который возвращает дату платежа и дату последней активности по платежу:

SELECT
        ContactId AS debtorId,
        t1.CreatedOn AS activityDate,
        t2.CreatedOn AS paymentDate
FROM Activity AS t1 INNER JOIN UsrPayments AS t2
        ON t1.ContactId = t2.UsrDebtorId
WHERE t1.CreatedOn = (
        SELECT max(CreatedOn) FROM Activity
        WHERE t1.ContactId = t2.UsrDebtorId
);

И есть некоторый код C#, где с помощью подзапроса я хочу определить дату последней активности по платежу, аналогично тому, как я это делаю выше на native SQL:

var selectNewPayments = (Select)new Select(userConnection)
        .Column("t1", "ContactId")
        .Column("t1", "CreatedOn")
        .Column("t2", "CreatedOn")
        .From("Activity").As("t1")
        .Join(JoinType.Inner, "UsrPayments").As("t2")
        .On("t1", "ContactId").IsEqual("t2", "UsrDebtorId")
        .Where("... здесь подзапрос и обращение к функции max() ...")
        as Select;

Как этот подзапрос написать?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Здравствуйте!
Все функции описаны по ссылке.

Пример:

SELECT 
C.Name,
(SELECT COUNT(*) FROM Activity A WHERE A.ContactId = C.Id) As ActivityCount
FROM Contact C

Перевод в С#:

var subSelect = new Select(userConnection)
                .Column(Func.Count(Column.Asterisk()))
.From("Activity").As("A")
.Where("C", "Id").IsEqual("A", "ContactId").As("ActivityCount")
var select = new Select(userConnection)
                .Column("C", "Name")
                .Column(subSelect)
.From("Contact").As("C")

Супер! Алексей, спасибо большое.

А можно то же самое, только не Select'ом а с помощью ESQ?

Здравствуйте, Олег!

Примеры доступны по ссылке:
https://www.terrasoft.ru/bpmonlinesdk/UsingEntitySchemaQuery.html

"Шамшин_Олег" написал:А можно то же самое, только не Select'ом а с помощью ESQ?

1. Делаете один esq запрос на содержимое подзапроса, выбираете из него, список Id, или чего вам нужно, в оригинальном посте подзапрос выбирал CreatedOn. Формируете массив этих CreatedOn.

2. В колбеке после возврата результата подзапроса, формируете новый esq запрос, с фильтрацией нужной колонки, в оригинальном посте CreatedOn на вхождение в массив ранее выбранных CreatedOn.

Т.к. фильтрация createColumnInFilterWithParameters спокойно проверит вхождение колонки и в массив.
Пример оторванный от контекста esq, рассматривает только создания фильтра, но такой фильтр подставленный в esq будет работать и в esq:
http://www.community.terrasoft.ru/forum/topic/11497#comment-50859

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

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

Для того, чтобы это сделать, следует создать колонку подзапроса:

111

Пример запроса:

SELECT
        "tbl_Invoice"."Amount" AS "Amount",
        "tbl_Invoice"."OwnerID" AS "OwnerID",
        (SELECT
                SUM("tbl_InvoiceSum"."Amount") AS "Amount"
        FROM
                "tbl_Invoice" AS "tbl_InvoiceSum"
        WHERE("tbl_InvoiceSum"."OwnerID" = "tbl_Invoice"."OwnerID")) AS "AmountSum"
FROM
        "tbl_Invoice" AS "tbl_Invoice"

Пример сервиса в приложении.

Нравится

Поделиться

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

Собственно, подзапросы разные бывают. Чащё даже не сумму вытягивают, а максимальное значение или первое подходящее по критерию (например, адрес контакта нужного типа).
Это настраивается в свойствах поля в подзапросе:
subquery

такой вопрос
есть следующий подзапрос в sq_Opportunity

	(SELECT
		SUM([tbl_Cashflow].[BasicAmount]) AS [BasicAmount]
	FROM
		[dbo].[tbl_Cashflow] AS [_tbl_Cashflow]
	WHERE([tbl_Cashflow].[OpportunityID] = [tbl_Opportunity].[ID] AND
		[tbl_Cashflow].[UseAsPandL] = :True)) AS [TourCreditSum],

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

я так понял оно и не должно подсчитывать (так как итоги подсчитываются SQL-запросом в БД, а не на основе датасета). Верно?
http://www.community.terrasoft.ru/forum/topic/5193

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

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

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

Добавив фільтр типу IN і в підзапиті чотири фільтри.

З головним фільтром все OK, а от до фільтрів підзапиту доступу отримати не вдається,-
говорить, що TestExpression.ExpressionSelectQuery null або не об'єкт.

Дивився поради в темі
Включение фильтра типа Exists.Достучаться до фильтров в Подзапросе :-)

Вставив "Dataset.SelectQuery.LoadUserFilters();"
очікуваного ефекту не отримав.

function edtContactIDOnPrepareSelectWindow(LookupDataControl, SelectWindow) {
        var Dataset             = LookupDataControl.DataField.LookupDataset;
        var UserType    = CIUEdit.UserType;
        var UserKind    = CIUEdit.UserKind;
//
        Dataset.SelectQuery.LoadUserFilters();
//
        var SelectQuery         = Dataset.SelectQuery;
        var     CIUFilter               =
                SelectQuery.Items(0).Filters.ItemsByCode('ConfigurationItemUser');
        EnableFilter(CIUFilter  ,'ConfigurationItemUser'        ,true);
       
        var SubSelectFilters =
                CIUFilter.TestExpression.ExpressionSelectQuery.Items(0).Filters;
        for (var i = 0; i SubSelectFilters.Count; i++) {
                MessageBox(SubSelectFilters.Items(i).Code);
        }
}

Нравится

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

Здається знайшов, - треба використовувати дещо інші члени для фільтра типу 'Include':

var ValuesExpressions = CIUFilter.ValuesExpressions;
var SubSelectFilters =
ValuesExpressions.Items(0).ExpressionSelectQuery.Items(0).Filters;

тоді конструкція

for (var i = 0; i < SubSelectFilters.Count; i++) {
     MessageBox(SubSelectFilters.Items(i).Code);
}

показує всі фільтри підзапиту і без виконання

Dataset.SelectQuery.LoadUserFilters();

Игорь, как раз работали над Вашим обращением. Рад что все получилось. Если будут дополнительные вопросы обращайтесь

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