3つのクエリで2つのDataTableから一意のIDを選択し、マージします

ハンク

データベースから入力された2つのDataTableがあります。1つはコアデータであり、もう1つは監査テーブルであり、コアデータのレコードが挿入、更新、または削除されたときに記録します。

注:削除されたレコードはコアデータには含まれませんが、監査履歴はあります。

最終的には、最新の「AUDITDATE」を持つ一意の「ID」のDataTableを取得し、その「AUDITDATE」の降順で並べ替えたいと思います。次に、最後に変更された一意のIDを降順で示すDataTableを作成できます。

「AUDITDATE」と「ID」はどちらも「yyyyMMddhhmmss」の形式のdoubleデータ型です。

だから私は3つのクエリを実行できると思っていました:

  1. コアデータに含まれる監査レコード(既存のものを教えてください)
  2. コアデータに含まれていない監査レコード(削除されたものを教えてください)
  3. どのコアレコードが監査データに含まれていないか(触れられていないものを教えてくれます)

    var setCore = new HashSet<double>(geometry.dtGEOM_TABLE_CORE.AsEnumerable().Select(p => p.Field<double>("ID")));
    var setAudit = new HashSet<double>(geometry.dtGEOM_TABLE_AUDIT.AsEnumerable().Select(p => p.Field<double>("ID")));
    
    var resultAuditInCore = geometry.dtGEOM_TABLE_AUDIT.AsEnumerable()
        .Select(r => new { AUDITDATE = r.Field<double>("AUDITDATE"), ID = r.Field<double>("ID"), STATUS = "EXISTING" })
        .Where(r => setCore.Contains(r.ID))
        .OrderByDescending(r => r.AUDITDATE)
        .GroupBy(r => r.ID)
        .CopyToDataTable();
    
    var resultAuditNotInCore = geometry.dtGEOM_TABLE_AUDIT.AsEnumerable()
        .Select(r => new { AUDITDATE = r.Field<double>("AUDITDATE"), ID = r.Field<double>("ID"), STATUS = "DELETED" })
        .Where(r => !setCore.Contains(r.ID))
        .OrderByDescending(r => r.AUDITDATE)
        .GroupBy(r => r.ID)
        .CopyToDataTable();
    
    var resultCoreNotInAudit = geometry.dtGEOM_TABLE_CORE.AsEnumerable()
        .Select(r => new { AUDITDATE = (double)0, ID = r.Field<double>("ID"), STATUS = "NA" })
        .Where(r => !setAudit.Contains(r.ID))
        .OrderByDescending(r => r.ID)
        .CopyToDataTable();
    

この後、「AUDITDATE」で3つすべての並べ替えを再度マージする予定でした。

問題:CopyToDataTable()は機能しませんが、削除すると機能します select()

質問:

  • DataTablesを出力するために3つのクエリを取得するにはどうすればよいですか?
  • DataTablesが作成されたら、それらをマージする方法は?
ハラルドコププールス

あなたは、aの結果がGroupBy一連のIGrouping<key, items>オブジェクトであることに気づいていますね。各グループには、異なる数の要素が含まれる場合があります。このようなシーケンスは、データテーブルに変換できません。

MSDNにSystem.Data.DataTableExtensions.CopyToDataTable<T>よると、ジェネリックパラメータTはDataRowです。私のコンパイラは、匿名クラスがDataRowではないため、GroupByの結果をCopyToDataTableに入力できないと文句を言います。

したがって、変更されていない、削除された、監査されたアイテムを1つの順序付けられたシーケンスに変換DataRowsする必要があります。このシーケンスは、テーブルに必要なデータを含むものに変換できます。


コアデータテーブルのアイテムには少なくともIDがあり、監査データテーブルの要素には少なくとも。がありAuditDateCoreDataIdコアデータテーブルの監査済みアイテムのIDを参照していると仮定します(少なくともアイテムが存在します)。

どうやらあなたはすべてのデータを1つのテーブルに入れたいのですが、私はあなたがこのデータをオブジェクトに持っていると思いますTableData

変更されていないアイテムはのテーブルにないためAuditedData、コアテーブルの変更されていないアイテムにはが必要TableDataです。

削除されたすべてのアイテムはコアデータに含まれなくなったため、AuditedDataテーブルの削除されたアイテムにもTableDataが必要です。

すべてのデータをDateTimeで並べ替える必要があるためTableData、AuditDateも含める必要があります。一部のアイテムは監査されません。それらのAuditDateはnullです。

TODO:監査されたことのないアイテムで並べ替える方法を決定しますか?注文した結果の最初または最後?*

class TableData
{
    DateTime? AuditDate {get; set;} // used to order by date. null if never audited
    ...
}

class CoreData
{
    public int Id {get; set;}     // int may be any other type
    public TableData {get; set;}  // all untouched items should have this
                                  // all others: choose what you want
    ...
}

class AuditData
{
    public DateTime AuditDate {get; set;}
    public int CoreId {get; set;}
    public TableData {get; set;}  // all deleted items should have this
                                  // all others: choose what you want
    ...
}

IEnumerable<CoreData> coreData = ...
IEnumerable<AuditData> auditedData = ...

LINQクエリを作成して、元のコアデータと監査済みデータを最後に述べたシーケンスに変換できると思います。

触れられない(編集も削除もされない)
アイテム= coreDataにはあるが、auditedDataにはないすべてのアイテム:

var auditedItemIds = auditedData
    .Select(auditedItem => auditedItem.CoreId)
    .Distinct();
IEnumerable<TableData> untouchedItems = coreData
    .Where(coreItem => !auditedItemIds.Contains(coreItem.Id))
    .Select(coreItem => coreItem.TableData;

削除されたアイテム
= (もう)含まれauditedDataていないすべてのアイテムcoreData最後のauditedDataアイテムのみが必要です

var coreItemIds = coreData.Select(coreItem => coreItem.Id)
    .Distinct();
IEnumerable<TableData> deletedItems = auditedData
    // take only the audited items that are not in core data anymore:
    .Where(auditedItem => !coreItemIds.Contains(auditedItem.CoreId)
    // group the remaining items by same CoreId
    .GroupdBy(
        auditedItem => auditedItem.CoreId,     // key of the group: coreId
        autitedItem => auditedItem.TableData); // elements of the group
    // from every group (= all audited items belonging to the same core item)
    // take the element with the newest date
    // = order by descending AuditDate and take FirstOrDefault
    // because a group is created you are certain there is an element in the group
    .Select(group => group
        .OrderbyDescending(groupElement => groupElement.AuditDate)
        .FirstOrDefault());

編集項目は
=の両方にあるすべてのアイテムcoreDataとでは、auditedDataあなたがしたい場合、私はわからないtableDataからcoreDataやからをauditedDataLINQクエリも同様です。

tableData最新の監査からのものが必要だと仮定します

var coreItemIds = coreData.Select(coreItem => coreItem.Id)
    .Distinct();
IEnumerable<TableData> newestAuditData = auditedData
    // take only auditedData that is still in coreData
    .Where(auditedItem => coreItemIds.Contains(auditedItem.CoreId)
    // group the remaining items by same CoreId
    .GroupdBy(
        auditedItem => auditedItem.CoreId,     // key of the group: coreId
        autitedItem => auditedItem.TableData); // elements of the group
    // from every group (= all audited items belonging to the same core item)
    // take the element with the newest date
    // = order by descending AuditDate and take FirstOrDefault
    // because a group is created you are certain there is an element in the group
    .Select(group => group
        .OrderbyDescending(groupElement => groupElement.AuditDate)
        .FirstOrDefault());

後の表現Whereは、削除されたアイテムでも監査対象のアイテムと同じであることに気づきましたか?

これで、これらすべての要素を並べ替える方法を決定し、それらをDataRowの1つのシーケンスに配置するだけです。

IOrderedEnumerable<TableData> OrderQueryResult(
    IEnumerable<TableData> unTouchedItems,
    IEnumerable<TableData> deletedItems,
    IEnumerable<TableData> auditedItems)
{
    // TODO decide what order to use
    return result;
}

class MyDataRow : DataRow
{
    MyDataRow(TableData tableData)
    {
        // in the constructor, extract the data you want in the DataRow
    }
}

IOrderedEnumerable<TableData> orderedTableData = OrderedQueryResult(
    untouchedItems, deletedItems, newestAuditData);
IEnumerable<MyDataRow> dataRows = orderedTableData
    .Select(tableData => new MyDataRow(tableData);
DataTable myTable = dataRows.CopyToDataTable();

最後に、データベースがすでに存在するのか、それとも現在開発中なのかはわかりません。同じデータを含む2つのテーブルがあるため、クエリは非常に困難です。1つは実際のデータを含み、もう1つはデータの履歴を含みます。次のテーブルがあれば、クエリははるかに簡単でした。

私はこれをEntity-Framework形式で記述します。他の方法を使用する場合は、そこからSQLテーブルを抽出できると確信しています。

class CoreData
{
    public int Id {get; set;}
    public ... NeverChangingItems {get; set;}

    public bool IsObsolete {get; set;}

    // HistoricData is data that might change through history
    public virtual ICollection<HistoricData> HistoricData {get; set;}
 }

 public class HistoricData
 {
      public int Id {get; set;}
      public DateTime AuditDate {get; set;}
      public ... ItemsThatChangeThroughoutHistory {get; set;}

      // foreign key to owning Core
      public int CoreDataId {get; set;}
      public virtual CoreData CoreData {get; set;}
 }

変更されないコアデータを含むテーブルと履歴を含むテーブルがある場合、3つのクエリははるかに簡単になります。さらに、要素が削除されることはないため、変更されていないコアデータのコピーを用意する必要はありません。

使用する方法では、削除されたアイテムも監査済みテーブルに残っているため、実際には削除されないことに注意してください。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

2つのMongodbコレクションをマージし、一意の値を選択します(pymongo)

分類Dev

一意のユーザーIDごとに最大3つのエントリを持つ最後のエントリを100個選択します

分類Dev

Postgresqlは、一意の学生IDごとに上位5つのマーク行を選択します

分類Dev

SQL Advancedwhere-2つのwhere選択をクエリでマージします

分類Dev

1つのSQLクエリで2つのテーブルをマージし、日付値を一意にします

分類Dev

テーブルのマージを解除して、2つの列から一意の値を作成します

分類Dev

データベース内の最新の一意のエントリを5つ選択します

分類Dev

マスターアレイからランダムで一意のアイテムを選択して、4つのアレイにロードします

分類Dev

IPで並べ替えてから、3つの一意のIPができるまでレコードを選択し続けます

分類Dev

2つの一意のフィールドのそれぞれに特定のIDを持つ行を選択し、3番目のフィールドの位置をカウントするクエリ

分類Dev

既存の2つの列、pythonから一意のIDを作成します

分類Dev

SQLクエリ2つのエントリが等しい場合は、3つのテーブルから4つのエントリを選択します

分類Dev

2つのレコードをマージして、一意のIDを作成します

分類Dev

3つのテーブルからクエリを選択しますSQL

分類Dev

2つの変数から一意のIDを識別します

分類Dev

MySQLクエリ:「Y」のようなキーがある列を見つけてから、別の列の一意のIDを使用して3番目の列を何かで更新しますか?

分類Dev

2つの列で同じ値を持つ一意のIDの新しいIDを選択して作成します

分類Dev

MySql-列からランダムな4つのデータ2つの異なる一意の値を選択します

分類Dev

別の列から少なくとも1つの値を示す一意のエントリを選択します

分類Dev

Linuxで2つのディレクトリをマージして、すべての一意のファイルを取得します

分類Dev

Java 8を使用して、一意のIDを持つ2つのリストのオブジェクトをマージする

分類Dev

SQLUnionサブクエリの一意のID-2つの結果を返します

分類Dev

Mysqlクエリを解決して、IDから一意を選択し、日付で並べ替えます

分類Dev

テーブル名に一意のIDを持つ複数のテーブルから情報を選択します

分類Dev

他の一意の列を持つ特定のレコードの最大値のみを選択しますか?

分類Dev

列Aから一意の値を選択し、列Bから一意の値を選択します

分類Dev

Rubyの2つの配列を一意のキーでマージします

分類Dev

mysqlでは、異なる列名を持つ2つのテーブルの2つのクエリからの一意のアイテムのみを表示するようにしています

分類Dev

配列から一意のIDを持つ最初のオブジェクトを取得し、それらを新しいリストに配置します

Related 関連記事

  1. 1

    2つのMongodbコレクションをマージし、一意の値を選択します(pymongo)

  2. 2

    一意のユーザーIDごとに最大3つのエントリを持つ最後のエントリを100個選択します

  3. 3

    Postgresqlは、一意の学生IDごとに上位5つのマーク行を選択します

  4. 4

    SQL Advancedwhere-2つのwhere選択をクエリでマージします

  5. 5

    1つのSQLクエリで2つのテーブルをマージし、日付値を一意にします

  6. 6

    テーブルのマージを解除して、2つの列から一意の値を作成します

  7. 7

    データベース内の最新の一意のエントリを5つ選択します

  8. 8

    マスターアレイからランダムで一意のアイテムを選択して、4つのアレイにロードします

  9. 9

    IPで並べ替えてから、3つの一意のIPができるまでレコードを選択し続けます

  10. 10

    2つの一意のフィールドのそれぞれに特定のIDを持つ行を選択し、3番目のフィールドの位置をカウントするクエリ

  11. 11

    既存の2つの列、pythonから一意のIDを作成します

  12. 12

    SQLクエリ2つのエントリが等しい場合は、3つのテーブルから4つのエントリを選択します

  13. 13

    2つのレコードをマージして、一意のIDを作成します

  14. 14

    3つのテーブルからクエリを選択しますSQL

  15. 15

    2つの変数から一意のIDを識別します

  16. 16

    MySQLクエリ:「Y」のようなキーがある列を見つけてから、別の列の一意のIDを使用して3番目の列を何かで更新しますか?

  17. 17

    2つの列で同じ値を持つ一意のIDの新しいIDを選択して作成します

  18. 18

    MySql-列からランダムな4つのデータ2つの異なる一意の値を選択します

  19. 19

    別の列から少なくとも1つの値を示す一意のエントリを選択します

  20. 20

    Linuxで2つのディレクトリをマージして、すべての一意のファイルを取得します

  21. 21

    Java 8を使用して、一意のIDを持つ2つのリストのオブジェクトをマージする

  22. 22

    SQLUnionサブクエリの一意のID-2つの結果を返します

  23. 23

    Mysqlクエリを解決して、IDから一意を選択し、日付で並べ替えます

  24. 24

    テーブル名に一意のIDを持つ複数のテーブルから情報を選択します

  25. 25

    他の一意の列を持つ特定のレコードの最大値のみを選択しますか?

  26. 26

    列Aから一意の値を選択し、列Bから一意の値を選択します

  27. 27

    Rubyの2つの配列を一意のキーでマージします

  28. 28

    mysqlでは、異なる列名を持つ2つのテーブルの2つのクエリからの一意のアイテムのみを表示するようにしています

  29. 29

    配列から一意のIDを持つ最初のオブジェクトを取得し、それらを新しいリストに配置します

ホットタグ

アーカイブ