2012-11-01 2 views
0

두 개의 데이터 스키마를 하나로 병합해야합니다. 나는 Schema1과 Schema2를 가지고있다. 이 두 가지를 Schema3에 결합해야합니다. 또한, 나는 데이터 집합을 쿼리하는 Select 문을 가지고 있지만 두 테이블 (Schema1과 Schema2 모두)을 포함하는 데이터 집합에서 select 문을 사용하고 테이블 인 새 테이블 schema3에 결합하는 방법을 알아낼 수 없습니다 두 테이블의 필드로 구성된 동일한 데이터 세트에 있습니다.두 테이블을 하나로 결합하기

스키마 1 ID, 식품, 도서, 쌀, 동굴

스키마 2 ID, 카펫, 문자열, 실행

스키마 3 ID, 식품, 도서, 쌀, 동굴, 카펫, 문자열, 실행

이 명령으로 Schema3 표를 채우

는 SQL 명령 :

Select * Schema1 [except ID] and all fields from Schema2 [exceptID] Inner Join 
Schema2 ON Schema1.ID = Schema2.ID 
Where ID = {dynamically defined variable 'X'} 

적절한 구문의 부족을 용서하십시오. 여기에서 다시 주요 문제는 select 문을 사용하여 데이터 집합을 쿼리하고 테이블을 결과로 채우는 것입니다. 이미 로컬로 데이터 집합을 채우기 때문에 내 DB에 정확하게 연결되지 않았습니다.

------ 편집 ------ 두 테이블의 쿼리에서 데이터 행 배열을 만드는 방법이 필요합니다.

+0

새로운 병합 된 DataTable이 필요하거나 익명 형식으로 충분합니까? –

+0

프로세스가 끝날 때 보고서 뷰어에 테이블 내용을 제공 할 수있는 한 어느 쪽이라도 상관이 없습니다. – Ccorock

+0

데이터베이스에서도 UNION 키워드를 사용할 수 있습니다. –

답변

2

another question에 대해 처음부터 작성한 확장 방법을 사용할 수 있습니다. 공통 키로 여러 테이블을 병합 할 수 있습니다. 아무 키도 그냥 기본 DataTable.Merge 방법을 사용합니다 지정되지 않은 경우 :

public static DataTable MergeAll(this IList<DataTable> tables, String primaryKeyColumn) 
{ 
    if (!tables.Any()) 
     throw new ArgumentException("Tables must not be empty", "tables"); 
    if(primaryKeyColumn != null) 
     foreach(DataTable t in tables) 
      if(!t.Columns.Contains(primaryKeyColumn)) 
       throw new ArgumentException("All tables must have the specified primarykey column " + primaryKeyColumn, "primaryKeyColumn"); 

    if(tables.Count == 1) 
     return tables[0]; 

    DataTable table = new DataTable("TblUnion"); 
    table.BeginLoadData(); // Turns off notifications, index maintenance, and constraints while loading data 
    foreach (DataTable t in tables) 
    { 
     table.Merge(t); // same as table.Merge(t, false, MissingSchemaAction.Add); 
    } 
    table.EndLoadData(); 

    if (primaryKeyColumn != null) 
    { 
     // since we might have no real primary keys defined, the rows now might have repeating fields 
     // so now we're going to "join" these rows ... 
     var pkGroups = table.AsEnumerable() 
      .GroupBy(r => r[primaryKeyColumn]); 
     var dupGroups = pkGroups.Where(g => g.Count() > 1); 
     foreach (var grpDup in dupGroups) 
     { 
      // use first row and modify it 
      DataRow firstRow = grpDup.First(); 
      foreach (DataColumn c in table.Columns) 
      { 
       if (firstRow.IsNull(c)) 
       { 
        DataRow firstNotNullRow = grpDup.Skip(1).FirstOrDefault(r => !r.IsNull(c)); 
        if (firstNotNullRow != null) 
         firstRow[c] = firstNotNullRow[c]; 
       } 
      } 
      // remove all but first row 
      var rowsToRemove = grpDup.Skip(1); 
      foreach(DataRow rowToRemove in rowsToRemove) 
       table.Rows.Remove(rowToRemove); 
     } 
    } 

    return table; 
} 

는이 방법으로 호출 할 수 있습니다 :

var tables= new[] { Schema1, Schema2}; 
DataTable Schema3 = tables.MergeAll("ID"); 

편집 :와 당신이 필요하지 않은 경우 새로운 DataTable 당신은 또한 Linq-To-DataSet (현재 VB.NET)를 사용할 수있는 통합 된 스키마

Dim schema3 = From r1 In schema1 
      Join r2 In schema2 On r1.Field(Of Int32)("ID") Equals r2.Field(Of Int32)("ID") 
      Select New With { 
       .ID = r1.Field(Of Int32)("ID"), 
       .Food = r1.Field(Of String)("Food"), 
       .Book = r1.Field(Of String)("Book"), 
       .Rice = r1.Field(Of String)("Rice"), 
       .Cave = r1.Field(Of String)("Cave"), 
       .Carpet = r2.Field(Of String)("Carpet"), 
       .Strings = r2.Field(Of String)("Strings"), 
       .Run = r2.Field(Of String)("Run") 
      } 
+0

그게 훌륭한 작품이지만, 내가 뭔가 더 간단하고 VB에서 바랬습니다. 나는 이것을 끝내 버릴지도 모른다. – Ccorock

+0

@Ccorock : C#을 (를) 유감스럽게 생각합니다. VB 코드로 변환 할 시간이 없습니다. 익명 형식 및 Linq VB.NET 접근 방식을 제공하기 위해 내 대답을 편집했습니다. –

+0

@Ccorock : 방금 VS 2005을 사용하고있는 것으로 나타났습니다. 그런 다음 불행히도 내 대답은 도움이되지 않습니다. –

0

이 시도 :

''' <summary> 
    ''' Merge two datatables that have a 1:1 relationship 
    ''' </summary> 
    ''' <param name="dtb1">Required Datatable.</param> 
    ''' <param name="dtb2">Required Datatable.</param> 
    ''' <param name="dtb1MatchField">Required String. Field name in dtb1 to use to match records</param> 
    ''' <param name="dtb2MatchField">Required String. Field name in dtb2 to use to match records</param> 
    ''' <remarks></remarks>' 
    Private Function MergeDataTables(ByVal dtb1 As DataTable, ByVal dtb2 As DataTable, ByVal dtb1MatchField As String, ByVal dtb2MatchField As String) As DataTable 
    Dim dtbOutput As DataTable = dtb1.Copy 
    Dim lstSkipFields As New List(Of String) 
    For Each dcl As DataColumn In dtb2.Columns 
     Try 
     dtbOutput.Columns.Add(dcl.ColumnName, dcl.DataType) 
     Catch ex As DuplicateNameException 
     lstSkipFields.Add(dcl.ColumnName) 
     End Try 
    Next dcl 
    'Merge dtb2 records that match existing records in dtb1' 
    Dim dtb2Temp As DataTable = dtb2.Copy 
    For int2 As Integer = dtb2Temp.Rows.Count - 1 To 0 Step -1 
     Dim drw2 As DataRow = dtb2Temp.Rows(int2) 
     Dim o2 As Object = drw2(dtb2MatchField) 
     For Each drw1 As DataRow In dtbOutput.Rows 
     Dim o1 As Object = drw1(dtb1MatchField) 
     If o1.ToString = o2.ToString Then 
      For Each dcl As DataColumn In dtb2Temp.Columns 
      If Not lstSkipFields.Contains(dcl.ColumnName) Then 
       drw1(dcl.ColumnName) = drw2(dcl.ColumnName) 
      End If 
      Next dcl 
      dtb2Temp.Rows.Remove(drw2) 
     End If 
     Next drw1 
    Next int2 
    'add rows that weren not in dtb1' 
    For Each drw2 As DataRow In dtb2Temp.Rows 
     Dim drw1 As DataRow = dtbOutput.NewRow 
     For Each dcl As DataColumn In dtb2Temp.Columns 
     drw1(dcl.ColumnName) = drw2(dcl.ColumnName) 
     Next dcl 
     dtbOutput.Rows.Add(drw1) 
    Next drw2 
    Return dtbOutput 
    End Function 
관련 문제