2013-04-25 2 views
3

행을 검색하는 데 사용하는 행 수가 약 50,000 인 DataTable을 가지고 있습니다. Select에는 와일드 카드 일치를 비롯한 여러 개의 AND 조건이 필요합니다. 나는 놀고 여러 단계에서 동일한 Select을 수행함으로써 실행 시간을 크게 줄일 수 있지만 AND 명령문의 순서를 변경해도 영향을 미치지 않는다는 것을 알았습니다.DataTable 복수 AND 조건으로 구현 선택

//This takes ~ 750 ms 
DataRow[] results = myDataTable.Select("Field1 LIKE '*" + term1 + "*'" + 
"AND Field2 = '" + term2 + "'" + 
"AND Field3 = '" + term3 + "'"); 

//This also takes ~750 ms 
DataRow[] results2 = myDataTable.Select("Field3 = '" + term3 + "'" + 
"AND Field2 = '" + term2 + "'" + 
"AND Field1 LIKE '*" + term1 + "*'"); 

//This takes 0.415 ms 
DataTable table1 = myDataTable.Select("Field3 = '" + term3+ "'").CopyToDataTable(); 
DataTable table2 = table1.Select("Field2 = '" + term2 + "'").CopyToDataTable(); 
DataRow [] results3 = table2.Select("Field1 LIKE '*" + term1 + "*'"); 

내 질문은 항상 기록의 수는 단계 사이에 감소 될 것이다 검색 있도록 SELECT 작업이 왼쪽에서 오른쪽으로 AND 조건을 평가하게하는 방법은 무엇입니까? 이것이 시간을 절약 할 수있는 좋은 방법 인 것 같습니다. 당신의 아이디어에 감사드립니다.

답변

4

당신은 Linq (메모를 사용할 수 있습니다 가장 느린 조건이 마지막 임) :

IEnumerable<DataRow> rows = myDataTable.AsEnumerable() 
    .Where(r => r.Field<string>("Field2") == term2 
      && r.Field<string>("Field3") == term3 
      && r.Field<string>("Field1").Contains(term1)); 

사용 CopyToDataTable 당신이 결과에서 새 DataTable을을 만들려면, ToArrayDataRow[]을 만들거나 그것을 떠나 새 컬렉션을 만들지 않고 결과를 열거 할 foreach를 사용합니다.

+0

팁 팀 Tim에게 감사드립니다. 크게 향상된 성능! – DaveH

0

아니요 .. 아니요. 데이터 테이블은 행별로 선택을 수행합니다. 이 같은 추가 확장 메서드를 만들 경우

DataRow [] results = myDataTable 
    .Select("Field3 = '" + term3+ "'").CopyToDataTable() 
    .Select("Field2 = '" + term2 + "'").CopyToDataTable() 
    .Select("Field1 LIKE '*" + term1 + "*'"); 

또는 ... :

정적 공개 된 DataRow []를 선택합니다 (이 IEnumerable을 행

당신은 조금 더 짧은 코드를 작성할 수 있습니다 문자열 필터) { return rows.CopyToDataTable(). 선택 (필터); 이 확장을 사용하여 }

만든다 코드도 짧은 :

DataRow [] results = myDataTable 
    .Select("Field3 = '" + term3+ "'") 
    .Select("Field2 = '" + term2 + "'") 
    .Select("Field1 LIKE '*" + term1 + "*'"); 

또는 :

static public DataRow[] Select(this DataTable dt, string firstFilter, params string[] filters) 
{ 
    DataRow[] result = dt.Select(firstFilter); 
    foreach(string filter in filters) 
     result = result.CopyToDataTable().Select(filter); 
    return result; 
} 

열기까지 방식 :

DataRow [] results = myDataTable.Select(
    "Field3 = '" + term3+ "'", 
    "Field2 = '" + term2 + "'", 
    "Field1 LIKE '*" + term1 + "*'"); 
+2

이것은 매우 비효율적 인 테이블을 필터링하기 위해 두 개의 새로운 DataTables와 세 개의 DataRow []를 메모리에 만듭니다. –

+0

맞음 ... 나는 호환성을 위해 가능한 한 그의 해결책에 가깝게 머물렀다. 나는 당신의 솔루션이 훨씬 더 빠르고 더 빨랐다는 것을 인정했지만, 같은 복잡한 식의 표준은 (등을 사용하면) 정규 표현식 등을 사용하는 것과 같은 새로운 문제를 던질 것이라고 상상할 수 있습니다. –