我有一个查询,我需要提高效率。
我将其分解为各个部分以查看效率楼层的位置,我目前有几个嵌套Select语句,这些是性能问题吗?
以下是其中一个示例:
SELECT AgreementID,
DueDate,
UpdatedAmountDue AS AmountDue,
COALESCE((SELECT SUM(UpdatedAmountDue)
FROM RepaymentBreakdown AS B
WHERE CONVERT(datetime, CONVERT(varchar, DueDate, 103), 103) <=
CONVERT(datetime, CONVERT(varchar, R.DueDate, 103), 103)
AND B.AgreementID = R.AgreementID),0) AS DueTD,
RN=ROW_NUMBER() OVER (Partition BY R.AgreementID ORDER BY DueDate)
FROM RepaymentBreakdown AS R
是否有更简洁有效的方法来获取DueTD的数据?
基本上,对于还款计划结果的每一行,我想得到:
AgreementID,
DueDate,
AmountDue,
AmountDueToDate (DueTD)
RowNumber.
我查询的表格结构如下:
AgreementID (int),
DueDate (datetime),
AmountDue (decimal(9,2)),
UpdatedAmountDue (decimal(9,2))*
* UpdatedAmountDue始终被引用,因为它是移动的数字,AmountDue始终是固定的,作为参考值。
答案 0 :(得分:1)
所以,我认为你可以通过删除转换来提升性能,就像这样:
select
AgreementID,
DueDate,
UpdatedAmountDue as AmountDue,
(
select sum(B.UpdatedAmountDue)
from RepaymentBreakdown as B
where B.DueDate <= R.DueDate and B.AgreementID = R.AgreementID
) as UpdatedAmountDue
from RepaymentBreakdown AS R
我知道在SQL Server 2008中计算运行总计的最快方法是使用递归CTE,请参阅我的答案Calculate a Running Total in SqlServer。在您的情况下,查询将是这样的:
create table #t (....., primary key (AgreementID, ord))
insert into #t (AgreementID, DueDate, UpdatedAmountDue, ord)
select AgreementID, DueDate, UpdatedAmountDue, row_number() over (partition by AgreementID, DueDate order by DueDate asc)
;with
CTE_RunningTotal
as
(
select T.ord, T.AgreementID, T.DueDate, T.UpdatedAmountDue as T.AmountDue, T.UpdatedAmountDue
from #t as T
where T.ord = 1
union all
select T.ord, T.AgreementID, T.DueDate, T.UpdatedAmountDue as T.AmountDue, T.UpdatedAmountDue + C.UpdatedAmountDue as UpdatedAmountDue
from CTE_RunningTotal as C
inner join #t as T on T.ord = C.ord + 1 and T.AgreementID = C.AgreementID
)
select AgreementID, DueDate, AmountDue, UpdatedAmountDue
from CTE_RunningTotal as C
option (maxrecursion 0)
答案 1 :(得分:-1)
您将日期时间转换为日期有几个问题。
首先,根据您的服务器语言设置,无法保证始终生成正确的结果。如果需要对日期时间值执行字符串操作,请始终使用CONVERT(,, 126)。
但更重要的是,它会阻止索引使用。而是使用CAST(DueDate AS DATE)
,因为优化器会将转换识别为索引安全。
之后您可能希望在AgreementId,DueDate和INCLUDE
UpdatedAmountDue上添加索引,或者更好地使其成为群集。
假设UpdatedAmountDue不能为NULL,你也可以摆脱COALESCE,因为总和总是包含当前行。