首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C# 合併多源 DataTable:按時間與 ID 關聯三張表生成匯總表

     編輯:程式設計疑難解答

場景描述

三個數據庫查詢得到結構相同的三張表(A庫、B庫、C庫),字段:time, id, err。需合併為一張匯總表:time, id, errA, errB, errC,三表按 time + id 一一對應。

核心算法:以 A 表為基準,查找 B/C 表對應行

using System;
using System.Data;

public DataTable MergeThreeTables(DataTable dtA, DataTable dtB, DataTable dtC) {
    DataTable result = new DataTable("Merged");
    result.Columns.Add("Time", typeof(string));
    result.Columns.Add("ID", typeof(int));
    result.Columns.Add("ErrA", typeof(int));
    result.Columns.Add("ErrB", typeof(int));
    result.Columns.Add("ErrC", typeof(int));

    // 建立 B、C 表的索引字典,鍵:time#id,值:err,提升查找性能
    var dictB = dtB.AsEnumerable()
        .ToDictionary(r => $"{r["time"]}#{r["id"]}", r => Convert.ToInt32(r["err"]));
    var dictC = dtC.AsEnumerable()
        .ToDictionary(r => $"{r["time"]}#{r["id"]}", r => Convert.ToInt32(r["err"]));

    foreach (DataRow rowA in dtA.Rows) {
        string time = rowA["time"].ToString();
        int id = Convert.ToInt32(rowA["id"]);
        int errA = Convert.ToInt32(rowA["err"]);
        string key = $"{time}#{id}";

        int errB = dictB.TryGetValue(key, out var vB) ? vB : 0;
        int errC = dictC.TryGetValue(key, out var vC) ? vC : 0;

        result.Rows.Add(time, id, errA, errB, errC);
    }
    return result;
}

關鍵點解析

  • 字典索引:將 B/C 表轉為 `Dictionary`,查找複雜度從 O(n) 降為 O(1),總體 O(n)。
  • 鍵設計:`time#id` 組合鍵確保唯一性,防止 time 或 id 重複導致衝突。
  • 缺失值處理:`TryGetValue` 找不到時默認 0,業務上可改為 -1 或 null。
  • 類型安全:`Convert.ToInt32` 防止 DBNull 拋異常,實際用擴展方法更優雅。

計算三列平均值(追問)

// 在合併循環內直接計算,或後續遍歷 result
foreach (DataRow row in result.Rows) {
    double avg = (Convert.ToDouble(row["ErrA"]) + 
                  Convert.ToDouble(row["ErrB"]) + 
                  Convert.ToDouble(row["ErrC"])) / 3.0;
    // 可新增列存儲
    // row["AvgErr"] = Math.Round(avg, 2);
}

或用 LINQ 一行生成平均列:

result.Columns.Add("AvgErr", typeof(double));
foreach (DataRow row in result.Rows) {
    row["AvgErr"] = new[] { row.Field<int>("ErrA"), row.Field<int>("ErrB"), row.Field<int>("ErrC") }.Average();
}

大數據量優化(百萬行+)

  1. 使用 `SqlBulkCopy` 直接在數據庫層面 JOIN 合併,避免拉取到內存。
  2. 或用 `PLINQ` 並行構建字典:`dtB.AsParallel().ToDictionary(...)`。
  3. 流式處理:按 time 分批讀取、合併、寫入目標,內存常數級。

總結

多源表合併核心是建立高效索引(字典/哈希),以基準表驅動查找。C# `DataTable` 配合 LINQ/Dictionary 代碼簡潔高效,注意類型轉換與空值處理即可。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved