1

背景

MySQLデータベースからSQL-Serverデータベース(レポートおよび後でSSAS-Cube用)にデータをインポートしています。同時にデータを正規化したい。Ticket_IDs他の有用な情報を含むテーブル内の1つのレコードに繰り返しをグループContact化し、サブテーブルContactDetailにrawdataを残します(Contactへの外部キーを使用)。したがって、のすべてのレコードにContactは一意のがありTicket_IDます。

インポートには強い型のデータセットを使用することにしました。今、私はすでにTicket_IDを追加したかどうかを検出するための最良の方法は何であるか疑問に思っています。すべてのループ(〜100000レコード)でそれをチェックできましたが、より良い/より速い方法があると思います。

簡略化されたサンプルデータ:

Ticket_ID    ID     fiContact
89442226     1      1
89442226     2      1
89442226     3      1
89442261     4      2
89442261     5      2
89442354     6      3
89442359     7      4
89442359     8      4
89442367     9      5
89442504     10     6

これはContact-tableである必要があります

Ticket_ID    idContact
89442226     1
89442261     2
89442354     3
89442359     4
89442367     5
89442504     6

質問

LINQ / LINQ-to-DataSetを使用して、Ticket_IDでグループ化し、すべてのContactRowのContactDetailRowsのリストを取得することは可能ですか?GroupBy -Extensionがあることは知っていますが、使用方法と、それが必要なことを実行するかどうかがわかりません(ContactDetail-Rowsを保持し、Ticket_IDをキーおよびList(of EmailRow)値として持つ辞書のようにします)。

これは私が持っているものです(簡略化):

    For Each srcEmail In src.email 'i want to group src.email by Ticket_ID'
        'so far i check for existence in every loop'
        Dim res = From c In dest.Contact
               Where c.Ticket_ID = srcEmail.ticket_id
        If Not res.Any Then
            'create new Contact
            Dim newContact = Me.dest.Contact.NewContactRow
            newContact.Ticket_ID = srcEmail.ticket_id
            ' ..... '
            dest.Contact.AddContactRow(newContact)
        End If
        'TODO: create ContactDetail row and add it to the DataTable '
    Next
  • src:型付きDataSet(MySQL)
  • src.email:入力されたDataTable=>にContactDetail
  • dest:型付きDataSet(SQL-Server)
  • dest.ContactタイプされたDataTable
  • dest.ContactDetailfkを使用してDataTableと入力しましたContact

私はまだLINQに精通しておらず、構文がC#でかなり異なるため、VB.NETを好みます。

編集:

@Magnusのおかげで、次のようになりました。

Dim emailsPerTicketID = src.email.ToLookup(Function(email) email.ticket_id)
For Each ticket In emailsPerTicketID
    'create new Contact
    Dim newContact = Me.dest.Contact.NewContactRow
    newContact.Ticket_ID = ticket.Key
    newContact.CreatedAt = ticket.First().modified_time
    ' ...... '
    dest.Contact.AddContactRow(newContact)
    'TODO: add now all EmailRows'
    For Each emailRow In ticket
       Dim newContactDetail = dest.ContactDetail.NewContactDetailRow
       newContactDetail.ContactRow = newContact
       newContactDetail.Interaction = emailRow.interaction
       ' .... '
       dest.ContactDetail.AddContactDetailRow(newContactDetail)
    Next
Next

これが、連絡先がすでに作成されているかどうかを検出するためのHashSetを使用した反復アプローチよりも高速であるかどうかを確認します。

4

2 に答える 2

1

私のVBは錆びていますが、これがそのショットです。

Dim ticketGroups = From c in dest.Contact
                    Group c By Ticket_ID = c.Ticket_ID 
                    Into Tickets = Group

For Each ticketGroup In ticketGroups
    For Each ticket in ticketGroup.Tickets
        ' Create the row, add it, etc.
        Dim newContact = Me.dest.Contact.NewContactRow
        newContact.Ticket_ID = ticketGroup.Ticket_ID
        ' .... '
        dest.Contact.AddContactRow(newContact)
    Next
Next

または、ループを毎回チェックする場合は、HashSetを使用して、毎回チケットIDをハッシュセットに追加し、メソッドを介してその存在をチェックすることができますContains。それはあなたがしていることよりも速いでしょうが、LINQのグループ化はHashSetよりも速いと思います。

于 2011-07-14T22:43:47.507 に答える
1

ルックアップ(辞書のようですが、代わりにキー/コレクションを使用)を使用するのが良い解決策になると思います。このようなもの:

var lookup = ds.Tables["src"].AsEnumerable().ToLookup(x => x.Field<int>("Ticket_ID"));
foreach (var row in ds.Tables["dest"].AsEnumerable())
{
    if(!lookup.Contains(row.Field<int>("Ticket_ID ")))
    {
        //create new Contact
    }
    else
    {
        //do other struff
    }
}

構文のいずれかをVBに変換するためのヘルプが必要な場合は、コメントしてください。

于 2011-07-14T22:45:22.430 に答える