2011-05-19 121 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