执行此查询时,我的性能非常低,
我看不出任何明显的东西,任何人都可以建议我通过它的最佳方式
CREATE TABLE #tmp_NominalPurchase (
NomCode varchar(16),
NomDesc varchar(61),
GoodsSold money
)
declare @Pos Int
select @Pos = 1
while @Pos <= (select max(dbo.fn_DCount(NValues,'~')) from pledger)
begin
INSERT INTO #tmp_NominalPurchase (NomCode, NomDesc, GoodsSold) (
select
a.keyCode NomCode,
a.descr NomDesc,
sum(convert(money, dbo.fn_Field(pl.NValues,'~', @Pos) )) GoodsSold
from pledger pl
inner join accts a
On dbo.fn_Field(pl.NCodes,'~', @Pos) = a.keycode
and (acctType='N' and pb='P' and category='cs')
where convert(datetime, pl.batch) >='2014-01-01'
and convert(datetime, pl.batch) <'2014-06-25'
group by a.keyCode, a.descr)
select @Pos = @Pos + 1
end
select o.* FROM
(
select t.NomCode,
t.NomDesc,
0 GoodsCost,
0 GoodsDisc,
sum(t.GoodsSold) GoodsSold,
'24/06/2014 05:01:14 PM' as LocalDateAndTime
from #tmp_NominalPurchase t
group by
t.NomCode,
t.NomDesc
) o
Order By o.NomCode Asc
DROP TABLE #tmp_NominalPurchase
答案 0 :(得分:1)
我看到的一个显而易见的事情是,在将where子句中的比较进行之前,您正在将pl.batch转换为字符串。这将打败任何可能阻止表扫描的索引。
您还在用户定义的函数fn_field上进行连接。不知道该功能的目的,我想知道这是否会产生问题。当我看到类似的东西时,我怀疑它就在那里,因为数据模式没有经过深思熟虑。
答案 1 :(得分:0)
没有重写的查询和性能大幅增加,这已经将查询运行时间从12秒减少到&lt; 1秒
改进的SQL
SELECT dbo.fn_Field(pl.NValues,'~',1) AS [nVals1], dbo.fn_Field(pl.Ncodes,'~',1) as [nCodes1], dbo.fn_Field(pl.NValues,'~',2) as [nVals2], dbo.fn_Field(pl.Ncodes,'~',2) as [nCodes2],
'x' AS x INTO #tmp_NominalPurchase
FROM pledger pl
WHERE convert(datetime, pl.batch) >='2014-06-01'
AND convert(datetime, pl.batch) <'2014-06-28'
SELECT a.keycode AS NomCode,
a.descr AS NomDesc,
max(0) AS goodsCost,
max(0) AS GoodsDisc,
sum(CAST (NValue AS money)) AS GoodsSold ,
'06/27/2014 11:44:47 AM' AS LocalDateAndTime
FROM
(SELECT [nVals1] AS NValue,[nCodes1] AS NCode
FROM dbo.#tmp_NominalPurchase tnp
UNION ALL SELECT [nVals2]AS NValue,[nCodes2] AS NCode
FROM dbo.#tmp_NominalPurchase tnp) x
INNER JOIN dbo.Accts a ON x.Ncode = a.keycode
AND acctType='N'
AND category='cs'
AND pb='P'
GROUP BY a.keycode,
a.descr
ORDER BY NomCode
DROP TABLE #tmp_NominalPurchase
获取计数的功能
Public Function getNCodeCount(ByVal sWhere) As Integer '00528591
Dim Ds As DataSet
Dim sqlSb As StringBuilder = New StringBuilder
Dim nCodesCount As Integer = 0
sqlSb.Append("SELECT isnull(max(dbo.fn_DCount(NValues,'~')),0) FROM PLEDGER PL with (nolock)" & sWhere)
Ds = SqlConnect.SqlNet.OpenSQLdataset(sqlSb.ToString)
If Ds Is Nothing Then GoTo report_failed
If Ds.Tables.Count < 1 Then
GoTo report_failed
End If
With Ds.Tables(0)
For Each r In .Rows
nCodesCount = r(0)
Next
End With
Return nCodesCount
Exit Function
report_failed:
Return 0
'00528591 END
End Function
构建SQL字符串并输出报告的功能
Public Function LedgerNominalListingReportPurchase(ByVal DateFrom As String, ByVal DateTo As String, ByVal SortType As String, Optional ByVal DetailReport As Boolean = False, Optional ByVal NominalCode As String = "") As DataView 'L754303 (163.47)
Dim sql As String = ""
Dim gs As New GeneralSQL
Dim aWhere As New ArrayList
Dim sWhere As String = ""
If IsDate(DateFrom) Then aWhere.Add("convert(datetime, pl.batch) >=" & gs.SqlDate(CDate(DateFrom)))
If IsDate(DateTo) Then aWhere.Add("convert(datetime, pl.batch) <" & gs.SqlDate(CDate(DateTo).AddDays(1)))
For Each s As String In aWhere
If sWhere = "" Then
sWhere &= " where "
Else
sWhere &= " and "
End If
sWhere &= s
Next
If Not DetailReport Then 'L754303 (163.47)
'NEW SQL (FASTER) 00528591
sql &= "SELECT max(dbo.fn_DCount(NValues,'~')) FROM PLEDGER"
Dim nCodeCount As Integer = (getNCodeCount(sWhere))
If nCodeCount = Nothing Or 0 Then
sql = "CREATE TABLE #tmp_NominalPurchase (NomCode varchar(16), NomDesc varchar(61), GoodsCost money, GoodsDisc money, GoodsSold money) SELECT * FROM #tmp_NominalPurchase DROP TABLE #tmp_NominalPurchase"
Else
Dim qCount As Integer = 1
sql = "SELECT "
While qCount <= nCodeCount
sql &= "dbo.fn_Field(pl.NValues,'~'," + qCount.ToString
sql &= ") "
sql &= " as [nVals" + qCount.ToString
sql &= "], "
sql &= "dbo.fn_Field(pl.Ncodes,'~'," + qCount.ToString
sql &= ") "
sql &= " as [nCodes" + qCount.ToString
sql &= "], "
qCount += 1
End While
sql &= " 'x' as x "
sql &= "INTO #tmp_NominalPurchase FROM pledger pl " & sWhere
sql &= "SELECT a.keycode as NomCode, a.descr as NomDesc,max(0) AS goodsCost,max(0) AS GoodsDisc, sum(cast (NValue AS money) ) AS GoodsSold "
sql &= String.Format(", '{0}' as LocalDateAndTime", Format(General.UserNow, vars.Ses.FmtDate & " " & "hh:mm:ss tt")) 'V759658 (163.31) - format the date column based on the CountryMode setting
sql &= " FROM ("
sql &= "SELECT [nVals1] AS NValue,[nCodes1] AS NCode FROM dbo.#tmp_NominalPurchase tnp "
qCount = 2
While qCount <= nCodeCount
sql &= " UNION all "
sql &= "SELECT [nVals" + qCount.ToString
sql &= "]AS NValue,[nCodes" + qCount.ToString
sql &= "] AS NCode FROM dbo.#tmp_NominalPurchase tnp"
qCount += 1
End While
sql &= ") x inner join dbo.Accts a on x.Ncode = a.keycode and acctType='N' AND category='cs' AND pb='P' group by a.keycode,a.descr "
sql &= "ORDER BY " & SortType
sql &= " DROP TABLE #tmp_NominalPurchase"
End If
End If
Return SqlConnect.SqlNet.OpenSQLdataset(sql).Tables(0).DefaultView '00529265
End Function