请帮我弄清楚我的代码。乍一看,一切都很简单。但它并没有按预期工作。我已经没有其他可以尝试的想法了。
我正在制作一份关于与付款人的和解的报告。数据由查询语言选择。不管它是哪种语言,只要说它与标准 SQL 几乎完全相似就足够了。所选数据由四部分组成:支付、调整、确认、应计。使用 UNION ALL 组合各个部分。当我从请求中删除付款、确认和应计费用,只留下调整时,报告将按其应有的方式工作,即,它显示数据库中的调整。当我运行完整的请求时,即付款、确认、应计费用被添加到调整中 - 调整会从最终结果的某个地方消失。为什么——这就是整个问题。看来它们不可能消失,因为在其余的子查询中 - 对于付款、确认、应计费用 - 零被明确输入到调整列中,因此,他们无法在任何进一步的数据转换期间更改调整值。尽管如此,他们还是改变了。
可以发现,在对所选数据进行后续处理的阶段,即使用GroupBy进行分组的阶段,调整消失了。但我不知道如何找出为什么会发生这种情况。请帮我出出主意。
请求代码,无需付款、确认、收费 - 仅调整:
/*Стандартные параметры*/
DECLARE @DateFrom AS [Parus.Business.Date];
DECLARE @DateTo AS [Parus.Business.Date];
DECLARE @ServOrg AS [Parus.Business.ServedOrganization];
/*Параметры-массивы*/
--DECLARE @Groups AS ArrayOf([ParusYug.Business.Payroll.Group]);
--DECLARE @GroupTypes AS ArrayOf([ParusYug.Business.Payroll.GroupType]);
--DECLARE @ServiceAndCompensation AS ArrayOf([ParusYug.Business.ParentsPayments.ServiceAndCompensation]);
--DECLARE @Counteragent AS ArrayOf([Parus.Business.Counteragent]);
--DECLARE @ServiceRecipient AS ArrayOf([ParusYug.Business.Payroll.ServiceRecipient]);
SELECT
Main.CSD,
Main.Payer AS Counteragent,
Main.[Group],
Main.ProvidedService AS ServiceProvide,
Main.ServiceRecipient,
Main.Service,
Main.Schedule,
Main.PaymentFrom,
Main.ChargedFrom,
Main.ChargedFrom - Main.PaymentFrom AS SaldoFrom,
Main.ChargedTo,
Main.PaymentTo,
Main.CorrPere,
Main.CorrVozvr,
Main.ChargedTo - Main.PaymentTo AS SaldoTo,
Main.PaymentFrom + Main.PaymentTo AS PaymentFromTo,
Main.ChargedFrom + Main.ChargedTo AS ChargedFromTo,
(Main.ChargedFrom - Main.PaymentFrom) + (Main.ChargedTo - Main.PaymentTo) AS SaldoFromTo,
Main.ChargingPayer,
Main.Payment,
Main.ChargeConfirm,
Main.PaymentDate,
Main.Src
FROM
(
SELECT
Base.CSD,
Base.PaymentDate,
Base.Src,
Base.Payer,
Base.[Group],
Base.ProvidedService,
Base.ProvidedService.BC,
Base.ServiceRecipient,
Base.Service,
Base.Schedule,
sum(Base.PaymentFrom) AS PaymentFrom,
sum(Base.ChargedFrom) AS ChargedFrom,
sum(Base.ChargedTo) AS ChargedTo,
sum(Base.PaymentTo) AS PaymentTo,
sum(Base.CorrPere) AS CorrPere,
sum(Base.CorrVozvr) AS CorrVozvr,
Base.ChargingPayer,
Base.Payment,
Base.ChargeConfirm
FROM
(
--1.5 Корректировка. Для каждой строки оплаты,
-- у которой нераспределенная сумма неважно какая и дата оплаты больше левой границы и меньше правой границы
-- и это корректировка, то есть префикс равен 'корр':
-- Дата, Услуга, График услуг, Ребенок, Группа, Плательщик, Организация,
-- Остаток оплат на начало 0
-- Начислено за услуги на начало 0
-- Оплата 0
-- Начислено за услуги 0
-- Корректировка переплата сумма оплаты, если не стоит галочка 'Возврат сумм', иначе 0
-- Корректировка возврат сумма оплаты, если стоит галочка 'Возврат сумм', иначе 0
SELECT
TRUE as CSD,
P.PaymentDate,
CASE WHEN P.Service IS NOT NULL
THEN
P.Service
ELSE
EMPTY([ParusYug.Business.ParentsPayments.ServiceAndCompensation])
END AS Service,
EMPTY([ParusYug.Business.ParentsPayments.ScheduleServices]) AS Schedule,
CASE WHEN P.ServiceRecipient IS NOT NULL
THEN
P.ServiceRecipient
ELSE
EMPTY([ParusYug.Business.Payroll.ServiceRecipient])
END AS ServiceRecipient,
CASE WHEN P.[Group] IS NOT NULL
THEN
P.[Group]
ELSE
EMPTY([ParusYug.Business.Payroll.Group])
END AS [Group],
P.PayCounteragent AS Payer,
P.Institution.ServedOrganization,
EMPTY([ParusYug.Business.ParentsPayments.ServiceProvide]) AS ProvidedService,
CONVERT([Parus.Business.Sum], 0) AS PaymentFrom,
CONVERT([Parus.Business.Sum], 0) AS ChargedFrom,
CONVERT([Parus.Business.Sum], 0) AS PaymentTo,
CONVERT([Parus.Business.Sum], 0) AS ChargedTo,
CONVERT([Parus.Business.Sum], CASE WHEN P.ReturnSum = FALSE THEN P.PayAmount ELSE 0 END) AS CorrPere,
CONVERT([Parus.Business.Sum], CASE WHEN P.ReturnSum = TRUE THEN P.PayAmount ELSE 0 END) AS CorrVozvr,
P.Identity AS Payment,
EMPTY([ParusYug.Business.ParentsPayments.ChargingPayer]) AS ChargingPayer,
EMPTY([ParusYug.Business.ParentsPayments.ChargeConfirm]) AS ChargeConfirm,
'Корректировка' AS Src
FROM [ParusYug.Business.ParentsPayments.Payment] P
WHERE (@DateTo IS NULL OR P.PaymentDate <= @DateTo)
AND (@DateFrom IS NULL OR P.PaymentDate >= @DateFrom)
--AND P.UnknownAmount <> 0
AND P.Institution.ServedOrganization = @ServOrg
--AND (@Counteragent IS NULL OR P.PayCounteragent IN (@Counteragent))
--AND (@Groups IS NULL OR P.[Group] IN (@Groups))
--AND (@ServiceAndCompensation IS NULL OR P.Service IN (@ServiceAndCompensation))
--AND (@ServiceRecipient IS NULL OR P.ServiceRecipient IN (@ServiceRecipient))
AND P.Prefix = 'корр'
) Base
--WHERE (Base.Payer IN (@Counteragent) OR @Counteragent IS NULL)
--AND (Base.[Group] IN (@Groups) OR @Groups IS NULL)
--AND
--(@GroupTypes IS NULL
-- OR Base.ProvidedService.GroupAttendance.[Group].GroupType IN (@GroupTypes)
-- OR Base.ProvidedService.GroupService.[Group].GroupType IN (@GroupTypes)
-- )
--AND (Base.Service IN (@ServiceAndCompensation) OR @ServiceAndCompensation IS NULL)
--AND (Base.ServiceRecipient IN (@ServiceRecipient) OR @ServiceRecipient IS NULL)
GROUP BY Base.Payer,
Base.[Group],
Base.ProvidedService,
Base.ProvidedService.BC,
Base.ServiceRecipient,
Base.Service,
Base.Schedule,
Base.ChargingPayer,
Base.Payment,
Base.ChargeConfirm,
Base.PaymentDate,
Base.Src,
Base.CSD
) Main;
付款请求代码(确认和费用类似,所以这里不再列出):
/*Стандартные параметры*/
DECLARE @DateFrom AS [Parus.Business.Date];
DECLARE @DateTo AS [Parus.Business.Date];
DECLARE @ServOrg AS [Parus.Business.ServedOrganization];
/*Параметры-массивы*/
DECLARE @Groups AS ArrayOf([ParusYug.Business.Payroll.Group]);
DECLARE @GroupTypes AS ArrayOf([ParusYug.Business.Payroll.GroupType]);
DECLARE @ServiceAndCompensation AS ArrayOf([ParusYug.Business.ParentsPayments.ServiceAndCompensation]);
DECLARE @Counteragent AS ArrayOf([Parus.Business.Counteragent]);
DECLARE @ServiceRecipient AS ArrayOf([ParusYug.Business.Payroll.ServiceRecipient]);
SELECT
Main.CSD,
Main.Payer AS Counteragent,
Main.[Group],
Main.ProvidedService AS ServiceProvide,
Main.ServiceRecipient,
Main.Service,
Main.Schedule,
Main.PaymentFrom,
Main.ChargedFrom,
Main.ChargedFrom - Main.PaymentFrom AS SaldoFrom,
Main.ChargedTo,
Main.PaymentTo,
Main.CorrPere,
Main.CorrVozvr,
Main.ChargedTo - Main.PaymentTo AS SaldoTo,
Main.PaymentFrom + Main.PaymentTo AS PaymentFromTo,
Main.ChargedFrom + Main.ChargedTo AS ChargedFromTo,
(Main.ChargedFrom - Main.PaymentFrom) + (Main.ChargedTo - Main.PaymentTo) AS SaldoFromTo,
Main.ChargingPayer,
Main.Payment,
Main.ChargeConfirm,
Main.PaymentDate,
Main.Src
FROM
(
SELECT
Base.CSD,
Base.PaymentDate,
Base.Src,
Base.Payer,
Base.[Group],
Base.ProvidedService,
Base.ProvidedService.BC,
Base.ServiceRecipient,
Base.Service,
Base.Schedule,
sum(Base.PaymentFrom) AS PaymentFrom,
sum(Base.ChargedFrom) AS ChargedFrom,
sum(Base.ChargedTo) AS ChargedTo,
sum(Base.PaymentTo) AS PaymentTo,
sum(Base.CorrPere) AS CorrPere,
sum(Base.CorrVozvr) AS CorrVozvr,
Base.ChargingPayer,
Base.Payment,
Base.ChargeConfirm
FROM
(
-- 1. Для каждой строки оплаты,
-- у которой нераспределенная сумма <> 0 и дата оплаты меньше правой границы
-- и это не корректировка:
-- Дата, Услуга, График услуг, Ребенок, Группа, Плательщик, Организация,
-- Остаток оплат на начало нераспределенная сумма, если дата меньше левой границы диапазона формирования, иначе 0
-- Начислено за услуги на начало 0
-- Оплата нераспределенная сумма, если дата больше или равна левой границы диапазона формирования, иначе 0
-- Начислено за услуги 0
-- Корректировка переплата 0
-- Корректировка возврат 0
SELECT
TRUE as CSD,
P.PaymentDate,
CASE WHEN P.Service IS NOT NULL
THEN
P.Service
ELSE
EMPTY([ParusYug.Business.ParentsPayments.ServiceAndCompensation])
END AS Service,
EMPTY([ParusYug.Business.ParentsPayments.ScheduleServices]) AS Schedule,
CASE WHEN P.ServiceRecipient IS NOT NULL
THEN
P.ServiceRecipient
ELSE
EMPTY([ParusYug.Business.Payroll.ServiceRecipient])
END AS ServiceRecipient,
CASE WHEN P.[Group] IS NOT NULL
THEN
P.[Group]
ELSE
EMPTY([ParusYug.Business.Payroll.Group])
END AS [Group],
P.PayCounteragent AS Payer,
P.Institution.ServedOrganization,
EMPTY([ParusYug.Business.ParentsPayments.ServiceProvide]) AS ProvidedService,
CONVERT([Parus.Business.Sum], CASE WHEN P.PaymentDate < @DateFrom THEN (case when ReturnSum <> True then P.UnknownAmount else -P.UnknownAmount end) ELSE 0 END) AS PaymentFrom,
CONVERT([Parus.Business.Sum], 0) AS ChargedFrom,
CONVERT([Parus.Business.Sum], CASE WHEN P.PaymentDate >= @DateFrom THEN (case when ReturnSum <> True then P.UnknownAmount else -P.UnknownAmount end) ELSE 0 END) AS PaymentTo,
CONVERT([Parus.Business.Sum], 0) AS ChargedTo,
CONVERT([Parus.Business.Sum], 0) AS CorrPere,
CONVERT([Parus.Business.Sum], 0) AS CorrVozvr,
P.Identity AS Payment,
EMPTY([ParusYug.Business.ParentsPayments.ChargingPayer]) AS ChargingPayer,
EMPTY([ParusYug.Business.ParentsPayments.ChargeConfirm]) AS ChargeConfirm,
'Оплата' AS Src
FROM [ParusYug.Business.ParentsPayments.Payment] P
WHERE (@DateTo IS NULL OR P.PaymentDate <= @DateTo)
AND P.UnknownAmount <> 0
AND P.Institution.ServedOrganization = @ServOrg
AND (@Counteragent IS NULL OR P.PayCounteragent IN (@Counteragent))
AND (@Groups IS NULL OR P.[Group] IN (@Groups))
AND (@ServiceAndCompensation IS NULL OR P.Service IN (@ServiceAndCompensation))
AND (@ServiceRecipient IS NULL OR P.ServiceRecipient IN (@ServiceRecipient))
AND P.Prefix <> 'корр'
UNION ALL
--1.5 Корректировка. Для каждой строки оплаты,
-- у которой нераспределенная сумма неважно какая и дата оплаты больше левой границы и меньше правой границы
-- и это корректировка, то есть префикс равен 'корр':
-- Дата, Услуга, График услуг, Ребенок, Группа, Плательщик, Организация,
-- Остаток оплат на начало 0
-- Начислено за услуги на начало 0
-- Оплата 0
-- Начислено за услуги 0
-- Корректировка переплата сумма оплаты, если не стоит галочка 'Возврат сумм', иначе 0
-- Корректировка возврат сумма оплаты, если стоит галочка 'Возврат сумм', иначе 0
SELECT
TRUE as CSD,
P.PaymentDate,
CASE WHEN P.Service IS NOT NULL
THEN
P.Service
ELSE
EMPTY([ParusYug.Business.ParentsPayments.ServiceAndCompensation])
END AS Service,
EMPTY([ParusYug.Business.ParentsPayments.ScheduleServices]) AS Schedule,
CASE WHEN P.ServiceRecipient IS NOT NULL
THEN
P.ServiceRecipient
ELSE
EMPTY([ParusYug.Business.Payroll.ServiceRecipient])
END AS ServiceRecipient,
CASE WHEN P.[Group] IS NOT NULL
THEN
P.[Group]
ELSE
EMPTY([ParusYug.Business.Payroll.Group])
END AS [Group],
P.PayCounteragent AS Payer,
P.Institution.ServedOrganization,
EMPTY([ParusYug.Business.ParentsPayments.ServiceProvide]) AS ProvidedService,
CONVERT([Parus.Business.Sum], 0) AS PaymentFrom,
CONVERT([Parus.Business.Sum], 0) AS ChargedFrom,
CONVERT([Parus.Business.Sum], 0) AS PaymentTo,
CONVERT([Parus.Business.Sum], 0) AS ChargedTo,
CONVERT([Parus.Business.Sum], CASE WHEN P.ReturnSum = FALSE THEN P.PayAmount ELSE 0 END) AS CorrPere,
CONVERT([Parus.Business.Sum], CASE WHEN P.ReturnSum = TRUE THEN P.PayAmount ELSE 0 END) AS CorrVozvr,
P.Identity AS Payment,
EMPTY([ParusYug.Business.ParentsPayments.ChargingPayer]) AS ChargingPayer,
EMPTY([ParusYug.Business.ParentsPayments.ChargeConfirm]) AS ChargeConfirm,
'Корректировка' AS Src
FROM [ParusYug.Business.ParentsPayments.Payment] P
WHERE (@DateTo IS NULL OR P.PaymentDate <= @DateTo)
AND (@DateFrom IS NULL OR P.PaymentDate >= @DateFrom)
--AND P.UnknownAmount <> 0
AND P.Institution.ServedOrganization = @ServOrg
--AND (@Counteragent IS NULL OR P.PayCounteragent IN (@Counteragent))
--AND (@Groups IS NULL OR P.[Group] IN (@Groups))
--AND (@ServiceAndCompensation IS NULL OR P.Service IN (@ServiceAndCompensation))
--AND (@ServiceRecipient IS NULL OR P.ServiceRecipient IN (@ServiceRecipient))
AND P.Prefix = 'корр'
) Base
--WHERE (Base.Payer IN (@Counteragent) OR @Counteragent IS NULL)
--AND (Base.[Group] IN (@Groups) OR @Groups IS NULL)
--AND
--(@GroupTypes IS NULL
-- OR Base.ProvidedService.GroupAttendance.[Group].GroupType IN (@GroupTypes)
-- OR Base.ProvidedService.GroupService.[Group].GroupType IN (@GroupTypes)
-- )
--AND (Base.Service IN (@ServiceAndCompensation) OR @ServiceAndCompensation IS NULL)
--AND (Base.ServiceRecipient IN (@ServiceRecipient) OR @ServiceRecipient IS NULL)
GROUP BY Base.Payer,
Base.[Group],
Base.ProvidedService,
Base.ProvidedService.BC,
Base.ServiceRecipient,
Base.Service,
Base.Schedule,
Base.ChargingPayer,
Base.Payment,
Base.ChargeConfirm,
Base.PaymentDate,
Base.Src,
Base.CSD
) Main;
调整值包含在CorrPere(超额支付调整)和CorrVozvr(退款调整)列中。通过查询检索数据后,它会受到许多额外的处理,我不会在这里介绍这些处理,因为它们不是问题。问题出在 GroupBy 处理中的某个地方,因为在处理之后,所有记录中的 CorrPere 和 CorrVozvr 列都变为零:
var data1 = data.GroupBy(
od => new
{
od.GroupName,
od.ServiceRecipientName,
od.PayerName
},
(index, items) =>
{
var first = items.FirstOrDefault(x => x.OD != null && x.OD.Service != null) ?? items.First();
return new
{
PayerId = first.PayerId,
Rest = items.Sum(i => i.Rest),
FinalRest = items.Sum(i => i.FinalRest),
Rate1 = first.Rate1,
Rate2 = first.Rate2,
Charged = items.Sum(i => i.Charged),
PayerName = first.PayerName,
Paid = items.Sum(i => i.Paid),
CorrPere = items.Sum(i => i.CorrPere),
CorrVozvr = items.Sum(i => i.CorrVozvr),
Index = Params.GroupByPayer ? 0 : ++numCounter,
ServiceRecipientName = first.ServiceRecipientName,
Number = first.OD.ServiceRecipient.Number.Value,
GroupName = first.GroupName,
ServiceName = first.ServiceName == null ? first.ServicePayName : first.ServiceName,
Fact1 = first.Fact1,
Fact2 = first.Fact2,
Benefit = first.Benefit,
Items = items,
CSD = first.CSD
};
})
.Where(p => p.CSD || ((p.Rest != 0m || p.FinalRest != 0m) && !p.CSD && !Params.ClosedServices))
.ToArray();
//debug
var tmp3 = data1.Where(d => d.CorrPere != 0 || d.CorrVozvr != 0);
Вот в этот tmp3 уже ничего не отбирается - tmp3.Count()=0. Куда могут пропадать в вышеприведенном коде значения CorrPere и CorrVozvr? подскажите пожалуйста. Ведь вроде бы суммирую их как все остальные числовые поля: Rest, Charged, Paid. Куда же пропадают значения?
Выяснено: корректировки не обнуляются, а не пропускаются условием
(хотел бы я знать, как расшифровывается у автора это CSD (тип его - Boolean), и для чего этот флаг служит) Не пропускаются условием по CSD потому, что двумя строками выше это CSD берется как
CSD = first.CSD, то есть довольно случайным образом. Это вообще законно так брать? По-моему, это косяк у автора. К сожалению, не знаю как такой косяк правильно лечить. Но знаю, что если взять Max() от CSD, то возьмется значение true, а нам это вполне подходит. Поэтому изменил последние строки кода следующим образом:Теперь корректировки не обнуляются. Но не вылезет ли это боком где-то дальше - не знаю. Кто знает - расскажите нам пожалуйста!