Sql-Server
拆分字元串函式
我對 Aaron Bertrand在這裡推薦的這個拆分字元串函式有疑問。
有了它,您可以提取兩個斜線之間的資訊。現在,如果我不僅要提取像伺服器名稱這樣的一條資訊,還要提取像星期幾這樣的第二條資訊。為了在一個結果集中獲取該資訊,我將如何重寫程式碼?
這是我的數據範例
E:\BaseData\RUK\HPP_Conversion_Detail\hpp_conversion_detail_report_2015_11_02.csv E:\BaseData\RUK\Manual_Review\manual_review_report_2015_11_01.csv E:\BaseData\RUK\Disputes\dispute_report_2015_11_01.csv E:\BaseData\RSE\HPP_Conversion_Detail\hpp_conversion_detail_report_2015_11_02.csv E:\BaseData\RSE\Manual_Review\manual_review_report_2015_11_01.csv E:\BaseData\RSE\Disputes\dispute_report_2015_11_01.csv
我對第二個和第三個斜線以及第三個和第四個斜線之間的所有內容感興趣。Geoff 的建議是個好主意。然後我得到了行中的結果。是否可以在其他列中返回結果?
謝謝!
使用 Aaron Bertrand在這裡推薦的。
CREATE FUNCTION dbo.SplitStringsOrdered ( @List NVARCHAR(2000), @Delimiter NVARCHAR(32) ) RETURNS TABLE AS RETURN ( SELECT rn = ROW_NUMBER() OVER (ORDER BY Number), Item FROM (SELECT Number, Item = LTRIM(RTRIM(SUBSTRING(@List, Number, CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number))) FROM (SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects) AS n(Number) WHERE Number <= CONVERT(INT, LEN(@List)) AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter ) AS y);
還有你的範例數據
CREATE TABLE #x (filepath NVARCHAR(2000)); INSERT #x VALUES ('E:\BaseData\RUK\HPP_Conversion_Detail\hpp_conversion_detail_report_2015_11_02.csv'), ('E:\BaseData\RUK\Manual_Review\manual_review_report_2015_11_01.csv'), ('E:\BaseData\RUK\Disputes\dispute_report_2015_11_01.csv'), ('E:\BaseData\RSE\HPP_Conversion_Detail\hpp_conversion_detail_report_2015_11_02.csv'), ('E:\BaseData\RSE\Manual_Review\manual_review_report_2015_11_01.csv'), ('E:\BaseData\RSE\Disputes\dispute_report_2015_11_01.csv')
然後你可以執行類似的東西
SELECT * FROM #x x CROSS APPLY dbo.SplitStringsOrdered(x.filepath, '\') sso WHERE sso.rn = 3
並退出第三部分。
有幾種方法可以到達多個部分。您可以從最後刪除 WHERE sso.rn = 3 ,但數據會分散在許多可能不適合您的行上。
使用子查詢可能對您有用。
SELECT * , Part3 = (SELECT sso.Item FROM dbo.SplitStringsOrdered(x.filepath, '\') sso WHERE sso.rn = 3) , Part5 = (SELECT sso.Item FROM dbo.SplitStringsOrdered(x.filepath, '\') sso WHERE sso.rn = 5) FROM #x x
程式碼突出顯示上方的警告錯誤地認為 \ 轉義了它後面的單引號,這在 SSMS/SQL-server 中實際上並非如此,除非您要求這種行為。
如果你想要一切,使用 MIN Pivot 的 hack 可能是最適合你的。
; WITH splits AS ( SELECT x.filepath , sso.rn , sso.Item FROM #x x CROSS APPLY dbo.SplitStringsOrdered(x.filepath, '\') sso ) SELECT * FROM ( SELECT splits.filepath , splits.rn , splits.Item FROM splits ) AS src PIVOT ( MIN(Item) FOR rn IN ([1],[2],[3],[4],[5]) ) AS pvt
但這最終看起來有點瘋狂,實際上並不像看起來那樣靈活或有用,而且總 MIN 很醜陋。
因此,您可以在沒有樞軸黑客和更多子查詢的情況下混合使用兩者。
;WITH splits AS ( SELECT x.filepath , sso.rn , sso.Item FROM #x x CROSS APPLY dbo.SplitStringsOrdered(x.filepath, '\') sso ) SELECT x.filepath , ( SELECT s.Item FROM splits s WHERE s.rn = 2 AND s.filepath = x.filepath ) , ( SELECT s.Item FROM splits s WHERE s.rn = 3 AND s.filepath = x.filepath ) , ( SELECT s.Item FROM splits s WHERE s.rn = ( SELECT MAX (splits.rn) FROM splits ) AND s.filepath = x.filepath ) FROM #x x