2011-05-19 120 views
3

我試圖從數據表中提取所有行,其中「代碼」遵循模式「Z ## A」。我嘗試了以下無濟於事:「表達式包含未定義 函數調用中期()」VB.Net Datatable選擇MID功能

Dim floods() As DataRow = arqTable.Select("mid(code,1,1)='Z' and isnumeric(mid(code,2,2)) and mid(code,4,1)='A'") 

返回錯誤

經過行使用FOR EACH循環,但我只是好奇,如果有一種方法可以簡單地使用數據表中選擇功能。

*編輯:順便說一句,使用「代碼如'Z%A'」是不會工作,因爲我特別尋找Z [數] [數] A而不是與Z [字母] [字母]一個。

+1

什麼是你的後端?您需要使用該語法。對於sql服務器,檢查出子字符串。 – Beth 2011-05-19 17:24:21

+0

真棒,子串作品!現在isnumeric會拋出一個未定義的函數 – DontFretBrett 2011-05-19 17:26:51

+0

,因爲它在您的後端未定義語法。嘗試在您的後端運行您的選擇語句。如果它在那裏不起作用,它會在你的代碼發送後不起作用。 – Beth 2011-05-19 17:28:51

回答

1

這一個工程

Dim r1() As DataRow = dt.Select("code LIKE 'Z%' and code LIKE '%A' and substring(code, 2, 1) >= '0' and substring(code, 2, 1) <= '9' and substring(code, 3, 1) >= '0' AND substring(code, 3, 1) <= '9' and len(code) = 4 ") 

如果你在所有關心效率看看這個簡單的例子從一個興趣點性能角度。 (粘貼到控制檯應用程序中)。

結果...

1000 RECORDS... 
SELECT: 00:00:00.0050357 matches 141 
VBLIKE: 00:00:00.0021198 matches 141 - %250.0 
VBRAW: 00:00:00.0007444 matches 141 - Infinity 
CREGEX: 00:00:00.0014745 matches 141 - %500.0 

10000 RECORDS... 
SELECT: 00:00:00.0530854 matches 1430 
VBLIKE: 00:00:00.0280535 matches 1430 - %189.3 
VBRAW: 00:00:00.0067957 matches 1430 - %883.3 
CREGEX: 00:00:00.0026389 matches 1430 - %2650.0 

100000 RECORDS... 
SELECT: 00:00:00.6141986 matches 13929 
VBLIKE: 00:00:00.1773157 matches 13929 - %346.9 
VBRAW: 00:00:00.0699633 matches 13929 - %889.9 
CREGEX: 00:00:00.0271444 matches 13929 - %2274.1 

1000000 RECORDS... 
SELECT: 00:00:06.2316807 matches 138987 
VBLIKE: 00:00:01.7882370 matches 138987 - %348.5 
VBRAW: 00:00:00.7093068 matches 138987 - %878.8 
CREGEX: 00:00:00.2714249 matches 138987 - %2299.3 

代碼

Imports System.Text.RegularExpressions 

Module Module1 

    Public RegEx_Code As New Regex("^Z[0-9][0-9]A$", RegexOptions.Compiled) 

    Sub Main() 
     Dim trials() As Integer = {1000, 10000, 100000, 1000000} 'data sizes to test 
     For Each recCnt As Integer In trials 
      'build test data that is sort of similar. 
      Dim dt As New DataTable 
      dt.Columns.Add("code", GetType(String)) 
      For iQ As Integer = 0 To recCnt - 1 
       dt.Rows.Add(If(iQ Mod 4 = 0, "Z", "X") & Chr(Int(Rnd() * 15) + 48) & Chr(Int(Rnd() * 12) + 48) & If(iQ Mod 2 = 0, "A", "Y")) 
      Next 

      'test SELECT 
      Dim sw1 As Stopwatch = Stopwatch.StartNew 
      Dim r1() As DataRow = dt.Select("code LIKE 'Z%' and code LIKE '%A' and substring(code, 2, 1) >= '0' and substring(code, 2, 1) <= '9' and substring(code, 3, 1) >= '0' AND substring(code, 3, 1) <= '9' and len(code) = 4 ") 
      sw1.Stop() 

      'test VB built in LIKE 
      Dim sw2 As Stopwatch = Stopwatch.StartNew 
      Dim r2 As New List(Of DataRow)(recCnt \ 20) 
      Dim rInd2 As Integer = dt.Columns("code").Ordinal 
      For Each r As DataRow In dt.Rows 
       If CStr(r(rInd2)) Like "Z##A" Then 
        r2.Add(r) 
       End If 
      Next 
      r2.TrimExcess() 
      sw2.Stop() 

      Dim sw3 As Stopwatch = Stopwatch.StartNew 
      Dim r3 As New List(Of DataRow)(recCnt \ 20) 
      Dim rInd3 As Integer = dt.Columns("code").Ordinal 
      For Each r As DataRow In dt.Rows 
       Dim value As String = CStr(r(rInd3)) 
       If value.Length = 4 AndAlso IsNumeric(value.Substring(1, 1)) AndAlso IsNumeric(value.Substring(2, 1)) AndAlso value.StartsWith("Z") AndAlso value.EndsWith("A") Then 
        r3.Add(r) 
       End If 
      Next 
      r3.TrimExcess() 
      sw3.Stop() 

      'test Compiled Regular Expression. 
      Dim sw4 As Stopwatch = Stopwatch.StartNew 
      Dim r4 As New List(Of DataRow)(recCnt \ 20) 
      Dim rInd4 As Integer = dt.Columns("code").Ordinal 
      For Each r As DataRow In dt.Rows 
       If RegEx_Code.IsMatch(CStr(r(rInd4))) Then 
        r4.Add(r) 
       End If 
      Next 
      r4.TrimExcess() 
      sw4.Stop() 
      Console.WriteLine(recCnt & " RECORDS...") 
      Console.WriteLine("SELECT: " & sw1.Elapsed.ToString & " matches " & r1.Length) 
      Console.WriteLine("VBLIKE: " & sw2.Elapsed.ToString & " matches " & r2.Count & " - " & CDbl(sw1.ElapsedMilliseconds/sw2.ElapsedMilliseconds).ToString("%0.0")) 
      Console.WriteLine("VBRAW: " & sw3.Elapsed.ToString & " matches " & r3.Count & " - " & CDbl(sw1.ElapsedMilliseconds/sw3.ElapsedMilliseconds).ToString("%0.0")) 
      Console.WriteLine("CREGEX: " & sw4.Elapsed.ToString & " matches " & r3.Count & " - " & CDbl(sw1.ElapsedMilliseconds/sw4.ElapsedMilliseconds).ToString("%0.0")) 
      Console.WriteLine() 

     Next 

     Console.ReadLine() 
    End Sub 

End Module 
+0

令人印象深刻的答案! – DontFretBrett 2011-06-24 19:48:50

0

這工作:

arqTable.Select("code LIKE 'Z%' and code LIKE '%A' and substring(code, 2, 1) BETWEEN '0' AND '9' and substring(code, 3, 1) BETWEEN '0' AND '9'") 
+0

:(該表達式包含不支持的運算符之間' – DontFretBrett 2011-05-20 14:48:19

+0

什麼框架Mircea?我限於3.5 – DontFretBrett 2011-05-20 14:56:22

+0

如果不支持之間,你總是可以使用> =和<= – Beth 2011-05-20 14:59:37

0

嗨 您可以使用解決方案通過米爾恰Dogaru

建議作爲 arqTable.Select(「代碼LIKE 'Z%' 和代碼LIKE '%A'和子串(碼,2,1)之間的 '0' AND '9' 和子串(碼,3,1)之間的 '0' 和 '9「')

與一個條件 長度(代碼)= 4

爲follow--

arqTable.Select("code LIKE 'Z%' and code LIKE '%A' and substring(code, 2, 1) BETWEEN 
'0' AND '9' and substring(code, 3, 1) BETWEEN '0' AND '9' and length(code) = 4 ") 
+0

謝謝,但請參閱Mircea的建議以及不支持的操作符 – DontFretBrett 2011-05-23 18:58:51

+0

我想告訴你關於這個條件.. 什麼你必須把你的代碼 – 2011-06-29 13:28:08