爲什麼查詢使用用戶定義的函數通過包含外連接的多個連接的查詢變慢?該函數的原因是修改一個字符串,以便按數字排序。排序字符串意味着100 < 99
。函數重新格式99 as 099
。所以,099 < 100
。它允許其他非數字值保持不變。訪問2007年用戶定義的函數加入緩慢
問題查詢使用函數通過帶連接的查詢。返回100行需要27秒。具有函數但是在一個表上的查詢需要亞秒。用查詢加入查詢的SQL替換是亞秒。沒有函數的查詢與連接的查詢是亞秒。主表是517行的tblTests。函數操作的列是文本列fldPurity。
tblTests
fldTestsID autonumber
fldPurity Text. field size 50. Indexed (Duplicates OK). Zero Length No.
這裏是功能碼。注意不同的輸入。
Public Function SortablePercent(ByVal pVar As Variant) As String
'------------------------------------------------------------------
' Purpose: Formats a string that may contain numbers or text values.
' The string percent may contain % or + characters. Ignore
' those characters during comparison. A string may start with numeric
' characters, but end with alpha characters. Compute the length of the resulting
' numeric characters. Length 3 is 100, no change. Prepend leading zeros to length 2
' or 1 numerics. Do not add prepend to values starting with text.
' Coded by: 2013-08-05 Henry Helgen
' Arguments: pVar: The string to be formatted.
' To Test: From the debug (immediate) window:
' X = "97+%"
' ? SortablePercent(X)
' 097
' X = "98"
' ? SortablePercent(X)
' 098
' X = "99.9"
' ? SortablePercent(X)
' 099.9
' X = "100"
' Print SortablePercent(X)
' 100
' X = "Reagent Grade"
' ? SortablePercent(X)
' Reagent Grade
' X = "85% & 15% H2O"
' ? SortablePercent(X)
' 085 & 15 H2O
'------------------------------------------------------------------
Dim strHold As String 'working string
Dim lenNum As Integer 'length of leading integer portion of number
' remove whitespace, %, + characters
strHold = Replace(Replace(Nz(Trim(pVar), ""), "%", ""), "+", "")
If IsNumeric(strHold) Then 'the entire string is numeric
lenNum = Len(CStr(Int(strHold)))
'Fill with leading zeros
strHold = Switch(lenNum = 3, strHold, lenNum = 2, "0" & strHold, lenNum = 1, "00" & strHold)
ElseIf IsNumeric(Left(strHold, 2)) Then '
strHold = "0" & strHold
ElseIf IsNumeric(Left(strHold, 1)) Then
strHold = "00" & strHold
End If 'numeric
SortablePercent = strHold
End Function
在這裏是使用功能對查詢慢查詢與使用函數在一個表(< 1秒)
SELECT tblTests.fldPurity,
SortablePercent([fldPurity]) AS temp2,
Count(*) AS RcdCount
FROM tblTests
GROUP BY tblTests.fldPurity, SortablePercent([fldPurity])
ORDER BY SortablePercent([fldPurity]);
這裏快速查詢連接(27秒),
SELECT parm_TestConcatReferenceDatasetExposure.fldPurity,
SortablePercent([fldPurity]) AS temp2, Count(*) AS RcdCount
FROM parm_TestConcatReferenceDatasetExposure
GROUP BY parm_TestConcatReferenceDatasetExposure.fldPurity,
SortablePercent([fldPurity])
ORDER BY SortablePercent([fldPurity]);
這裏快速查詢無功能查詢連接(< 1秒)
SELECT parm_TestConcatReferenceDatasetExposure.fldPurity,
Count(*) AS RcdCount
FROM parm_TestConcatReferenceDatasetExposure
GROUP BY parm_TestConcatReferenceDatasetExposure.fldPurity;
下面是使用的功能SQL局部近似的快速查詢在一個表(< 1秒)
SELECT tblTests.fldPurity,
IIf(IsNumeric(Replace(Replace(Nz(Trim([fldPurity]),""),"%",""),"+","")),CDbl(Replace(Replace(Trim([fldPurity]),"%",""),"+","")),Trim([fldPurity])) AS tempPurity,
Count(*) AS RcdCount
FROM tblTests
GROUP BY tblTests.fldPurity
ORDER BY IIf(IsNumeric(Replace(Replace(Nz(Trim([fldPurity]),""),"%",""),"+","")),CDbl(Replace(Replace(Trim([fldPurity]),"%",""),"+","")),Trim([fldPurity]));
下面是查詢與聯接
SELECT q_Test.fldTestsID, q_DatasetTreatment.fldDatasetsID,
q_DatasetTreatment.fldExposureEffectsID, q_Test.fldValidated,
q_Test.fldPollutantID, q_Test.fldPollutantName, q_Test.fldPollutantCAS,
q_Test.fldModeOfActionID, q_Test.fldModeOfAction, q_Test.fldPollutantTypeID,
q_Test.fldPollutantType, q_Test.fldSpeciesID, q_Test.fldClass, q_Test.fldGenus,
q_Test.fldSpecies, q_Test.fldCommonName, q_Test.fldTestTypeID,
q_Test.fldTestType, q_Test.fldTechniqueID, q_Test.fldTechnique,
q_Test.fldConcUnits, q_Test.fldDescription AS fldConcUnitDescription,
q_Test.fldMRID, q_Test.fldCETISID, q_Test.fldHardness, q_Test.fldSalinity,
q_Test.fldpH, q_Test.fldTemperature, q_Test.fldPurity, q_Test.fldDO,
q_Test.fldAcute, q_Test.fldUser, q_Test.fldComments,
IIf([q_sumTestReference].[fldTestsID] Is Not Null,[ConcatRef],"") AS CombinedRef,
q_DatasetTreatment.fldBiolVarNameID, q_DatasetTreatment.fldBiolVarName,
q_DatasetTreatment.fldLifeStageID, q_DatasetTreatment.fldLifeStage,
q_DatasetTreatment.fldDataTypeID, q_DatasetTreatment.fldDataType,
q_DatasetTreatment.fldGenerationID, q_DatasetTreatment.fldGeneration,
q_DatasetTreatment.fldEffectTypeID, q_DatasetTreatment.fldEffectType,
q_DatasetTreatment.fldDurationDays, q_DatasetTreatment.fldBVUnits,
q_DatasetTreatment.fldDescription AS fldBVUnitDescription,
q_DatasetTreatment.fldReportedNOEC, q_DatasetTreatment.fldReportedLOEC,
q_DatasetTreatment.fldTreatmentNum, q_DatasetTreatment.fldControlTypeID,
q_DatasetTreatment.fldControlType, q_DatasetTreatment.fldReplicateNum,
q_DatasetTreatment.fldPseudoReplicateNum, q_DatasetTreatment.fldNumberExposed,
q_DatasetTreatment.fldMeasuredConcentration,
q_DatasetTreatment.fldNominalConcentration, q_DatasetTreatment.fldBiolVarValue
FROM q_sumTestReference
RIGHT JOIN (q_Test
LEFT JOIN q_DatasetTreatment
ON q_Test.fldTestsID = q_DatasetTreatment.fldTestsID)
ON q_sumTestReference.fldTestsID = q_Test.fldTestsID
ORDER BY q_Test.fldTestsID, q_DatasetTreatment.fldDatasetsID,
q_DatasetTreatment.fldTreatmentNum, q_DatasetTreatment.fldReplicateNum;
我想使用的功能如它更簡單,代碼更簡潔。有什麼建議麼?我在this post on SQL Server user-defined functions看到它逐行評估。這是否意味着SQL查詢中的複雜解析語句就像我的第4個示例是正確的?
如果您有一個包含數字的字符串,請使用'Val(your_string)'使它按數字順序排序。我不確定你需要一個UDF,而內建的'Val()'函數可以使查詢更快。 – HansUp