2016-11-09 4 views
3

Мне нужен альтернативный способ упрощения этого кода.Ошибка SQL Server упрощает код из-за нескольких соединений

Этот код вычисляет возраст остатков клиента в зависимости от графика погашения кредита. Фильтры 1-7 дней, 8-30, 31-60 .... и так далее, пока не дойдете до 181 и выше

with membersWithLoans as -- gets members with loan 
(
    select 
     a.memberid, a.loanid, a.loanamt, a.intamt 
    from 
     loanmst a 
    where 
     loandt <= '12/19/2016' 
     and status = 'O' 
) 
,selectPaymentToDate as -- gets payments of the members to date 
(
    select 
     b.loanid, sum(a.princollamt) as princollamt1, 
     sum(a.intcollamt) as intcollamt1 
    from 
     collectiondtl a 
    inner join 
     membersWithLoans b on a.loanid = b.loanid 
    where 
     a.accdate <= '12/19/2016' 
    group by 
     b.loanid) 
,selectBalanceToDate as -- gets the balance of member to date 
(
    select 
     b.loanid, 
     sum(a.princeamt) as prinBalanceToDate, 
     sum(a.instamt) as intBalanceToDate, 
     sum(a.insamt) as insuBalanceToDate 
    from 
     loandtl a 
    inner join 
     membersWithLoans b on a.loanid = b.loanid 
    where 
     a.duedt <= '12/19/2016' 
    group by 
     b.loanid) 
, combineBalanceWithpayment as -- combine payment and balance 
(
    select a.loanid,a.loanamt, a.intamt, 
(case 
when b.prinBalanceToDate is null then 0 
else b.prinBalanceToDate end) as prinBalanceToDate2, 
(case 
when b.intBalanceToDate is null then 0 
else b.intBalanceToDate end) as intBalanceToDate2, 
(case 
when b.insuBalanceToDate is null then 0 
else b.insuBalanceToDate end) as insuBalanceToDate2, 
(case 
when c.princollamt1 is null then 0 
else c.princollamt1 end) as PrincipalCollectiontoDate, 
(case 
when c.intcollamt1 is null then 0 
else c.intcollamt1 end) as IntCollectiontoDate, 

cast(((case 
when b.prinBalanceToDate is null then 0 
else b.prinBalanceToDate 
end) 
- 
(case 
when c.princollamt1 is null then 0 
else c.princollamt1 end))as decimal(10,2)) as Arrears 
from 
membersWithLoans a 
left join selectBalanceToDate b 
on a.loanid=b.loanid 
left join selectPaymentToDate c 
on a.loanid=c.loanid 
) 

,filterNegativeArrears as 
(
select * 
from 
combineBalanceWithpayment 
where Arrears > 0 
) 

код выше получает информацию о члене

,select1To7days as -- this code gets amount to be paid in a specific schedule 
(
select b.loanid, 
    sum((case 
    when a.princeamt is null then 0 
    else a.princeamt end))as prin7Daysbalance 

from loandtl a 
inner join membersWithLoans b 
on a.loanid=b.loanid 
where 
    a.duedt > DATEADD(day,-7,'12/19/2016') 
     and 
    a.duedt<='12/19/2016' 
group by b.loanid 
) 

,select8to30days as -- this code gets amount to be paid in a specific schedule 
(
select b.loanid, 
    sum((case 
    when a.princeamt is null then 0 
    else a.princeamt end))as prin8To30Daysbalance 
from loandtl a 
inner join membersWithLoans b 
on a.loanid=b.loanid 
where 
    a.duedt<=DATEADD(day,-7,'12/19/2016') 
    and a.duedt > DATEADD(day,-30,'12/19/2016') 
group by b.loanid 
) 

-- and so on ..... the filters for schedule is compose of 31 to 60days, 61 to 90 days, 
--121 to 180 days, 181 and above. there is no pattern since it the requirement on days may change 


, computePar1To7days as -- computes the 1 to 7 days 
(
select a.loanid, cast((a.arrears - a.Par1To7days) as decimal(10,2)) as deductedArrears, a.Par1To7days 
from 
(
    select a.loanid,a.arrears, 
    cast((case 
    when a.arrears >= b.prin7Daysbalance then b.prin7Daysbalance -- if the arrears is greater than the 7days balance to be collected then it will be show 
    else a.arrears end)as decimal(10,2))as Par1To7days -- else the remaining is the arrears 
    from 
    filterNegativeArrears a 
    left join select1To7days b 
    on a.loanid=b.loanid 
) a 
where cast((a.arrears - a.Par1To7days) as decimal(10,2)) > 0 
) 

,computePar8To30days as -- computes the 8 to 30 days 
(
select a.loanid, cast((a.arrears - a.Par8To30days)as decimal(10,2)) as deductedArrears, a.Par8To30days 
from 
(
    select a.loanid, a.deductedArrears as arrears, 
    cast((case 
    when (a.deductedArrears) > 0 
     then 
      (case 
       when (a.deductedArrears)>= b.prin8To30Daysbalance 
        then b.prin8To30Daysbalance 
       else (a.deductedArrears) 
      end) 
    else 0 end)as decimal(10,2))as Par8To30days 

    from computePar1To7days a 
    left join select8To30days b 
    on a.loanid=b.loanid 
) a 
where cast((a.arrears - a.Par8To30days) as decimal(10,2)) > 0 
) 
-- so on until all par is computed. 31 to 60 days, 61 to 90 days, 
--121 to 180 days, 181 and above. there is no pattern since it the requirement on days may change 

в Приведенный выше код получает сумму данных из конкретных графиков как 1 до 7 дней, 8-30 дней, 31 до 60 дней, 61 до 90 дней, 121 до 180 дней, 181 и выше

select a.*, 
b.Par1To7days, 
c.Par8To30days, 
d.Par31To60days, 
e.Par61To90days, 
f.Par91To120days, 
g.Par121To180days --, 
--h.Par181AndAbovedays 
from 

filterNegativeArrears a 
left join computePar1To7days b 
on a.loanid=b.loanid 
left join computePar8To30days c 
on a.loanid=c.loanid 
left join computePar31To60days d 
on a.loanid=d.loanid 
left join computePar61To90days e 
on a.loanid=e.loanid 
left join computePar91To120days f 
on a.loanid=f.loanid 
left join computePar121To180days g 
on a.loanid=g.loanid 
--left join computePar181AndAbovedays h 
-- on a.loanid=h.loanid 

код, указанный выше присоединяется к расчетному возрасту

код работает отлично и расчета штрафа

enter image description here

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

left join computePar181AndAbovedays h 
on a.loanid=h.loanid 

Проблема я начал встречая ошибку:

enter image description here

An expression services limit has been reached. Please look for potentially complex expressions in your query, and try to simplify them.

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

Можете ли вы предложить способы упростить этот запрос высоко ценится

+1

Side Примечание: Вы должны абсолютно избежать локалей формат даты в любом запросе. Например, 'DATEADD (день, -7, '12/19/2016 ')' в вашем запросе. Всегда используйте формат ISO, как показано в [DATE] (https://msdn.microsoft.ком/EN-US/библиотека/bb630352.aspx). Форматы: 'YYYY-MM-DD' или' YYYYMMDD'. –

ответ

1

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

Как? Ну, у вас есть множество CTE. Другой способ написать ваш запрос - материализовать CTE во временных таблицах перед фактическим запросом, а затем вместо этого использовать временные таблицы.


Например, этот CTE:

membersWithLoans as -- gets members with loan 
(
select a.memberid, a.loanid,a.loanamt,a.intamt 
from loanmst a 
where loandt<='12/19/2016' 
and status = 'O' 
) 

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

select a.memberid, a.loanid,a.loanamt,a.intamt 
into #membersWithLoans 
from loanmst a 
where loandt<='12/19/2016' 
and status = 'O' 

Это создаст временную таблицу #membersWithLoans, которые могут быть использованы в дальнейшем временном создания таблиц или в вашем окончательном запросе.

Чтобы проиллюстрировать далее, предположим, что вы внедрили все свои CTE во временные таблицы, у вас не было бы больше WITH. Вы бы, наконец, использовать временные таблицы в вашем окончательном SELECT запроса:

-- create all temporary tables (one of them being #filterNegativeArrears) 

select 
    a.*, 
    -- the rest of your selections 
from 
    #filterNegativeArrears a 
    -- the rest of the joined temporary tables 
-- the rest of your query (WHERE, ORDER BY etc) 
+0

@Mandz Hi Mandz. Нет, то, что вы определяете в предложении 'WITH', - это CTE aka ** C ** ommon ** T **, способный ** E ** xpressions. Сравните их с представлениями, которые вы определяете временно для использования в одном запросе. CTE не материализованы; когда ваш запрос запущен, CTE расширяются в вашем запросе подобно тому, как вы будете писать свой запрос с производными таблицами. –

+0

Это новый код для меня. Я попытаюсь прочитать временные таблицы. Я думал, что sql «with clause» - это временные таблицы. Я быстро задаю вопрос, могу ли я присоединиться к моим текущим подзапросам с новой временной таблицей? Образец Я поставлю свой результат на temp1, тогда я присоединяюсь к temp1 к предыдущему запросу sub? – Mandz

+0

@Mandz Да, вы можете. Я быстро обновляю свой ответ, чтобы проиллюстрировать. –

 Смежные вопросы

  • Нет связанных вопросов^_^