有點晚了這裏的聚會,但作爲一般規則,我鄙視所有功能與BEGIN .. END
,他們幾乎從來沒有每當我看到一個表現良好,而且由於這涵蓋了所有的標量函數(直到微軟實現inline scalar expressions),因爲這樣的我尋找一種提供類似可重用性的替代方案。在這種情況下,查詢可以被轉換爲內嵌表值函數:
CREATE FUNCTION dbo.RemoveNonAlphaCharactersTVF (@String NVARCHAR(1000), @Length INT)
RETURNS TABLE
AS
RETURN
( WITH E1 (N) AS
( SELECT 1
FROM (VALUES (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)) n (N)
),
E2 (N) AS (SELECT 1 FROM E1 CROSS JOIN E1 AS E2),
N (Number) AS (SELECT TOP (LEN(@String)) ROW_NUMBER() OVER(ORDER BY E1.N) FROM E2 CROSS JOIN E1)
SELECT Result = ( SELECT TOP (ISNULL(@Length, 1000)) SUBSTRING(@String, n.Number, 1)
FROM N
WHERE SUBSTRING(@String, n.Number, 1) LIKE '[a-Z]'
ORDER BY Number
FOR XML PATH('')
)
);
所有這樣做是使用數字的列表,以擴大出串入列,例如RA123 *JU23T
變爲:
Letter
------
R
A
1
2
3
*
J
U
2
3
T
不在數字字母然後被where子句除去行:
WHERE SUBSTRING(@String, n.Number, 1) LIKE '[a-Z]'
離開
Letter
------
R
A
J
U
T
然後@Length
參數限制的字符(在您的情況這將是4),然後使用XML連接重建字符串。我通常會使用FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
進行xml連接以允許使用xml字符,但由於我知道沒有我沒有打擾,因爲它是額外的開銷。
運行一些測試在此用的1,000,000行一個示例表:
CREATE TABLE dbo.T (String NVARCHAR(1000));
INSERT T (String)
SELECT TOP 1000000 t.String
FROM (VALUES ('Nagpur District'), ('Ill Fated'), ('RA123 *JU23'), ('MAC')) t (String)
CROSS JOIN sys.all_objects a
CROSS JOIN sys.all_objects B
ORDER BY a.object_id;
然後比較所述標量和內聯的UDF(稱爲如下):
SELECT COUNT(SUBSTRING(dbo.RemoveNonAlphaCharacters(t.String), 1, 4))
FROM T;
SELECT COUNT(tvf.Result)
FROM T
CROSS APPLY dbo.RemoveNonAlphaCharactersTVF (t.String, 4) AS tvf;
超過15的測試運行(可能對於一個準確的數字還不夠,但足以描繪圖片)標量UDF的平均執行時間爲11.824s,而內聯TVF的平均執行時間爲1.658,因此速度大約快85%。
你有沒有試圖以任何方式解決這個問題呢? – Tanner 2014-10-22 11:07:38
只需使用像這樣的解決方案來刪除非字母字符:http://stackoverflow.com/questions/1007697/how-to-strip-all-non-alphabetic-characters-from-string-in-sql-server,然後取前4個字符。 – Tanner 2014-10-22 11:10:26