using CYQ.Data.SQL; using System; using System.Collections.Generic; using System.Text; namespace CYQ.Data.Table { public partial class MDataTable { internal int joinOnIndex = -1; /// /// 用于关联表的列名,不设置时默认取表主键值 /// public string JoinOnName { get { if (joinOnIndex > -1) { return Columns[joinOnIndex].ColumnName; } return string.Empty; } set { if (!string.IsNullOrEmpty(value)) { joinOnIndex = Columns.GetIndex(value); if (joinOnIndex == -1) { Error.Throw("not exist the column name : " + value); } } } } /// /// 两表LeftJoin关联 /// /// 关联表 /// 追加显示的列,没有指定则追加关联表的所有列 /// public MDataTable Join(MDataTable dt, params string[] appendColumns) { return MDataTableJoin.Join(this, dt, appendColumns); } /// /// 两表LeftJoin关联 /// /// 关联表名 /// 关联的字段名,设置Null则自动取表主键为关联名 /// 追加显示的列,没有指定则追加关联表的所有列 /// public MDataTable Join(object tableName, string joinOnName, params string[] appendColumns) { return MDataTableJoin.Join(this, Convert.ToString(tableName), joinOnName, appendColumns); } } /// /// 表间的关联关系 /// class MDataTableJoin { internal static MDataTable Join(MDataTable dtA, string tableName, string joinOnName, params string[] appendColumns) { MDataTable dtB = null; using (MAction action = new MAction(tableName, dtA.Conn)) { if (!action.Data.Columns.Contains(joinOnName)) { joinOnName = action.Data.Columns.FirstPrimary.ColumnName; } //action.SetAopState(CYQ.Data.Aop.AopOp.CloseAll); action.dalHelper.IsAllowRecordSql = false;//屏蔽SQL日志记录 2000数据库大量的In条件会超时。 if (appendColumns.Length > 0) { List items = new List(appendColumns.Length + 1); items.AddRange(appendColumns); if (!items.Contains(joinOnName)) { items.Add(joinOnName); } action.SetSelectColumns(items.ToArray()); } string whereIn = SqlCreate.GetWhereIn(action.Data[joinOnName].Struct, dtA.GetColumnItems(dtA.joinOnIndex, BreakOp.NullOrEmpty, true), action.DalType); dtB = action.Select(whereIn); dtB.JoinOnName = joinOnName; } return Join(dtA, dtB, appendColumns); } internal static MDataTable Join(MDataTable dtA, MDataTable dtB, params string[] columns) { //记录 ID as PID 映射的列名,中间记录,修改dtB的列名,后面还原 Dictionary mapName = new Dictionary(); #region 判断条件 int aIndex = dtA.joinOnIndex; if (aIndex == -1 && dtA.Columns.FirstPrimary != null) { aIndex = dtA.Columns.GetIndex(dtA.Columns.FirstPrimary.ColumnName); } int bIndex = dtB.joinOnIndex; if (bIndex == -1 && dtB.Columns.FirstPrimary != null) { bIndex = dtB.Columns.GetIndex(dtB.Columns.FirstPrimary.ColumnName); } if (aIndex == -1 || bIndex == -1) { Error.Throw("set MDataTable's JoinOnName first"); } #endregion #region 构建新表及表结构 MDataTable joinTable = new MDataTable("V_" + dtA.TableName); joinTable.Columns.AddRange(dtA.Columns.Clone()); if (columns.Length == 0) { joinTable.Columns.AddRange(dtB.Columns.Clone()); } else { foreach (string column in columns) { string[] items = column.Split(' '); string name = items[0]; MCellStruct ms = null; if (dtB.Columns.Contains(name)) { ms = dtB.Columns[name].Clone(); } if (items.Length > 1) { name = items[items.Length - 1]; if (ms == null && dtB.Columns.Contains(name)) { ms = dtB.Columns[name].Clone(); } } if (ms != null) { if (ms.ColumnName != name) { dtB.Columns[ms.ColumnName].ColumnName = name;//修改DtB的列名,结尾再还原。 mapName.Add(name, ms.ColumnName); ms.ColumnName = name; } joinTable.Columns.Add(ms); } } } #endregion List noFind = new List(); Dictionary yesFind = new Dictionary(StringComparer.OrdinalIgnoreCase); string v1 = string.Empty; MDataRow row, joinRow; int count = dtB.Rows.Count; for (int i = 0; i < dtA.Rows.Count; i++) { row = dtA.Rows[i]; if (count == 0 || row[aIndex].IsNullOrEmpty || noFind.Contains(row[aIndex].StringValue)) { joinRow = joinTable.NewRow(true); joinRow.LoadFrom(row);//后载加A表(同名则复盖) } else { v1 = row[aIndex].StringValue; if (yesFind.ContainsKey(v1)) // 找到已匹配的数据 { string[] items = yesFind[v1].Split(','); foreach (string item in items) { joinRow = joinTable.NewRow(true); joinRow.LoadFrom(dtB.Rows[int.Parse(item)]);//先加载B表 joinRow.LoadFrom(row);//后载加A表(同名则复盖) } } else { bool isFind = false; for (int j = 0; j < dtB.Rows.Count; j++) { if (v1 == dtB.Rows[j][bIndex].StringValue)//找到 { joinRow = joinTable.NewRow(true); joinRow.LoadFrom(dtB.Rows[j]);//先加载B表 joinRow.LoadFrom(row);//后载加A表(同名则复盖) isFind = true; if (yesFind.ContainsKey(v1)) { yesFind[v1] = yesFind[v1] + "," + j; } else { yesFind.Add(v1, j.ToString()); } } } if (!isFind) { noFind.Add(v1); joinRow = joinTable.NewRow(true);//找不到时,只加载A表。 joinRow.LoadFrom(row);//后载加A表(同名则复盖) } } } } //还原DtB的列 if (mapName.Count > 0) { foreach (KeyValuePair item in mapName) { dtB.Columns[item.Key].ColumnName = item.Value; } } #region 注销临时变量 noFind.Clear(); noFind = null; yesFind.Clear(); yesFind = null; mapName = null; #endregion return joinTable; } #region 匹配单条数据 已注释 /* internal static MDataTable Join(MDataTable dtA, MDataTable dtB, params string[] columns) { #region 判断条件 int aIndex = dtA.joinOnIndex; if (aIndex == -1 && dtA.Columns.FirstPrimary != null) { aIndex = dtA.Columns.GetIndex(dtA.Columns.FirstPrimary.ColumnName); } int bIndex = dtB.joinOnIndex; if (bIndex == -1 && dtB.Columns.FirstPrimary != null) { bIndex = dtB.Columns.GetIndex(dtB.Columns.FirstPrimary.ColumnName); } if (aIndex == -1 || bIndex == -1) { Error.Throw("set MDataTable's JoinOnName first"); } #endregion #region 构建新表及表结构 MDataTable joinTable = new MDataTable("V_" + dtA.TableName); joinTable.Columns.AddRange(dtA.Columns.Clone()); Dictionary keyValue = new Dictionary(); if (columns.Length == 0) { joinTable.Columns.AddRange(dtB.Columns.Clone()); } else { foreach (string column in columns) { if (dtB.Columns.Contains(column)) { joinTable.Columns.Add(dtB.Columns[column].Clone()); } } } #endregion string v1 = string.Empty; MDataRow row, joinRow; MDataCell cell; int count = dtB.Rows.Count; for (int i = 0; i < dtA.Rows.Count; i++) { joinRow = joinTable.NewRow(true); row = dtA.Rows[i]; if (count > 0) { cell = dtA.Rows[i][aIndex]; if (!cell.IsNullOrEmpty) { v1 = cell.strValue; if (keyValue.ContainsKey(v1)) // 找到已匹配的数据 { if (keyValue[v1] > -1) { joinRow.LoadFrom(dtB.Rows[keyValue[v1]]);//先加载B表 } } else { bool isFind = false; for (int j = 0; j < dtB.Rows.Count; j++) { if (v1 == dtB.Rows[j][bIndex].strValue) { joinRow.LoadFrom(dtB.Rows[j]); keyValue.Add(v1, j); isFind = true; break; } } if (!isFind) { keyValue.Add(v1, -1); } } } } joinRow.LoadFrom(row);//后载加A表(同名则复盖) } keyValue.Clear(); keyValue = null; return joinTable; } */ #endregion } }