SELECT
B.AccountBranchID
,B.VoucherNo
,B.BranchName AS BranchName
,B.InvoiceNo
,CONVERT(VARCHAR, B.InvoiceDate, 103) AS InvoiceDate
,CONVERT(VARCHAR, B.VoucherDate, 103) AS VoucherDate
,B.CustomerName
,B.RefID
,LN.AccountName AS LedgerName
,b.SalesPersonName AS SalesPersonName
,LN.LedgerCode
,B.AgentName
,B.ShipperName
,B.Segment
,B.TransactionType
,B.JobNo
,CONVERT(VARCHAR, B.JOBDate, 103) AS JOBDate
,B.MAWBNo
,B.HAWBNo
,B.AccountName
,B.LedgerCode AS AccountLedgerCode
,B.CurrencyCode
,ISNULL(B.Amount, 0) AS Amount
,B.ChargeExRate
,(CASE B.CRDR
WHEN 'CR' THEN (B.ChargeBaseAmount * -1)
ELSE B.ChargeBaseAmount
END) AS ChargeBaseAmount
,(CASE B.CRDR
WHEN 'CR' THEN 'Credit'
ELSE 'Debit'
END) AS CRDR
FROM VW_VoucherTR AS B
INNER JOIN VW_VoucherTR AS LN
ON B.VoucherID = LN.VoucherID
WHERE B.CompanyID = @CompanyID
AND (CASE @Type
WHEN 'I' THEN B.InvoiceDate
ELSE B.VoucherDate
END) BETWEEN ISNULL(@FromDate, (SELECT
FYearStart
FROM Secmst_FinancialYear
WHERE FyearId = @yearID)
) AND ISNULL(@ToDate, GETDATE())
AND (@Segment IS NULL
OR B.Segment = @Segment)
AND (@BranchMappingID IS NULL
OR B.BranchMappingID = @BranchMappingID)
AND B.VoucherTypeCode IN ('sv')
AND B.IsDeleted = 0
AND (B.GroupName <> 'Sundry Creditors'
AND B.GroupName <> 'Sundry Debtors')
AND LN.GroupName IN ('Sundry Debtors', 'Sundry Creditors')
答案 0 :(得分:0)
BETWEEN中的子查询可能正在杀死你。你看过执行计划了吗?
BETWEEN ISNULL(@FromDate, (
SELECT FYearStart
FROM Secmst_FinancialYear
WHERE FyearId = @yearID
))
AND ISNULL(@ToDate, GETDATE())
正在发生的事情是你在每一行都运行该查询,而且根据我的外表,这是不必要的,因为你只需要那里的静态日期(不是基于连接的行的任何东西。)
试试这个:
DECLARE @FromDateActual datetime = ISNULL(@FromDate, (
SELECT FYearStart
FROM Secmst_FinancialYear
WHERE FyearId = @yearID
));
DECLARE @ToDateActual datetime = ISNULL(@ToDate, GETDATE());
SELECT B.AccountBranchID
,B.VoucherNo
,B.BranchName AS BranchName
,B.InvoiceNo
,convert(VARCHAR, B.InvoiceDate, 103) AS InvoiceDate
,convert(VARCHAR, B.VoucherDate, 103) AS VoucherDate
,B.CustomerName
,B.RefID
,LN.AccountName AS LedgerName
,b.SalesPersonName AS SalesPersonName
,LN.LedgerCode
,B.AgentName
,B.ShipperName
,B.Segment
,B.TransactionType
,B.JobNo
,convert(VARCHAR, B.JOBDate, 103) AS JOBDate
,B.MAWBNo
,B.HAWBNo
,B.AccountName
,B.LedgerCode AS AccountLedgerCode
,B.CurrencyCode
,ISNULL(B.Amount, 0) AS Amount
,B.ChargeExRate
,(
CASE B.CRDR
WHEN 'CR'
THEN (B.ChargeBaseAmount * - 1)
ELSE B.ChargeBaseAmount
END
) AS ChargeBaseAmount
,(
CASE B.CRDR
WHEN 'CR'
THEN 'Credit'
ELSE 'Debit'
END
) AS CRDR
FROM VW_VoucherTR AS B
INNER JOIN VW_VoucherTR AS LN ON B.VoucherID = LN.VoucherID
WHERE B.CompanyID = @CompanyID
AND (
CASE @Type
WHEN 'I'
THEN B.InvoiceDate
ELSE B.VoucherDate
END
) BETWEEN @FromDateActual
AND @ToDateActual
AND (
@Segment IS NULL
OR B.Segment = @Segment
)
AND (
@BranchMappingID IS NULL
OR B.BranchMappingID = @BranchMappingID
)
AND B.VoucherTypeCode IN ('sv')
AND B.IsDeleted = 0
AND (
B.GroupName <> 'Sundry Creditors'
AND B.GroupName <> 'Sundry Debtors'
)
AND LN.GroupName IN (
'Sundry Debtors'
,'Sundry Creditors'
)
除此之外,您可以考虑添加非聚集索引。查询分析器甚至可以建议一对。但是你需要小心,具体取决于数据的使用和加载方式,因为太多的索引或大的索引会导致其他地方出现进一步的性能问题(行插入,页面碎片等)。
答案 1 :(得分:0)
可能有很多原因,但有一点很明显。以下部分不是sargable。
(CASE @Type
WHEN 'I' THEN B.InvoiceDate
ELSE B.VoucherDate
END) BETWEEN ISNULL(@FromDate, (SELECT
FYearStart
FROM Secmst_FinancialYear
WHERE FyearId = @yearID)
) AND ISNULL(@ToDate, GETDATE())
应该重写为sargable,以便可以使用索引。
SELECT @FromDate = ISNULL(@FromDate, (SELECT
TOP 1 FYearStart
FROM Secmst_FinancialYear
WHERE FyearId = @yearID)) )
SELECT @ToDate = ISNULL(@ToDate, GETDATE())
SELECT
...
WHERE
...
AND
((@Type='I' AND B.InvoiceDate BETWEEN @FromDate AND @ToDate)
OR
(@Type<>'I' AND B.VoucherDate BETWEEN @FromDate AND @ToDate))
AND
...
当然,正确的索引是如何加速查询的方式,如果InvoiceDate,VoucherDate等上没有索引,那么你的查询将使用全表扫描而不是索引搜索,它会很慢。