tijian_tieying/web/cyqdata-master/Table/MDataTableJoin.cs
2025-02-20 12:14:39 +08:00

327 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 用于关联表的列名,不设置时默认取表主键值
/// </summary>
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);
}
}
}
}
/// <summary>
/// 两表LeftJoin关联
/// </summary>
/// <param name="dt">关联表</param>
/// <param name="appendColumns">追加显示的列,没有指定则追加关联表的所有列</param>
/// <returns></returns>
public MDataTable Join(MDataTable dt, params string[] appendColumns)
{
return MDataTableJoin.Join(this, dt, appendColumns);
}
/// <summary>
/// 两表LeftJoin关联
/// </summary>
/// <param name="tableName">关联表名</param>
/// <param name="joinOnName">关联的字段名设置Null则自动取表主键为关联名</param>
/// <param name="appendColumns">追加显示的列,没有指定则追加关联表的所有列</param>
/// <returns></returns>
public MDataTable Join(object tableName, string joinOnName, params string[] appendColumns)
{
return MDataTableJoin.Join(this, Convert.ToString(tableName), joinOnName, appendColumns);
}
}
/// <summary>
/// 表间的关联关系
/// </summary>
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<string> items = new List<string>(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<string>(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<string, string> mapName = new Dictionary<string, string>();
#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<string> noFind = new List<string>();
Dictionary<string, string> yesFind = new Dictionary<string, string>(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<string,string> 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<string, int> keyValue = new Dictionary<string, int>();
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
}
}