From 079abab4e5e9ee33d71a7f96512725a79299282a Mon Sep 17 00:00:00 2001 From: YHS Date: Fri, 5 Jan 2024 11:06:06 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E8=A7=A3=E5=86=B3.ToPivotTable(it=20=3D>?= =?UTF-8?q?=20it.day,=20it=20=3D>new{=20it.name},=20it=20=3D>=20it.Sum(x?= =?UTF-8?q?=20=3D>=20x.count))=E7=9A=84=E5=87=A0=E4=B8=AA=E9=97=AE?= =?UTF-8?q?=E9=A2=98=201=20it.name=20=E4=B8=BA=E7=A9=BA=E5=80=BC=E6=97=B6?= =?UTF-8?q?=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8=E7=B4=A2=E5=BC=95=E8=B6=85?= =?UTF-8?q?=E5=87=BA=E7=95=8C=E5=80=BC=E5=BC=82=E5=B8=B8=202=20=E5=BD=93it?= =?UTF-8?q?.name=20=E7=9A=84=E5=80=BC=E4=B8=AD=20=E6=9C=89"T0=20=3D=20T1?= =?UTF-8?q?=20=3D=20T2"=E7=B1=BB=E4=BC=BC=E6=83=85=E5=86=B5=E6=98=AF?= =?UTF-8?q?=E4=BC=9A=E6=88=AA=E6=96=AD=E5=AD=97=E7=AC=A6=E4=B8=B2=EF=BC=8C?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E4=B8=BA"T0"=203=20=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E8=BD=AC=E5=8C=96=E6=95=88=E7=8E=87=EF=BC=8C=E7=8E=B0=E5=9C=A8?= =?UTF-8?q?=E6=89=80=E8=8A=B1=E6=97=B6=E9=97=B4=E5=8F=AA=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E4=B9=8B=E5=89=8D=E7=9A=841/4=E5=B7=A6=E5=8F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Src/Asp.NetCore2/MySqlTest/a9_ToPivot.cs | 126 ++++++++++++++++++ .../SqlSugar/Utilities/DataTableExtensions.cs | 79 ++++++----- 2 files changed, 165 insertions(+), 40 deletions(-) create mode 100644 Src/Asp.NetCore2/MySqlTest/a9_ToPivot.cs diff --git a/Src/Asp.NetCore2/MySqlTest/a9_ToPivot.cs b/Src/Asp.NetCore2/MySqlTest/a9_ToPivot.cs new file mode 100644 index 000000000..a976e128c --- /dev/null +++ b/Src/Asp.NetCore2/MySqlTest/a9_ToPivot.cs @@ -0,0 +1,126 @@ +#region using +using OrmTest; +using SqlSugar; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +#endregion + +namespace MySqlTest +{ + public class _a9_ToPivot + { + + public static void Init() + { + + var db = DbHelper.GetNewDb(); + db.CodeFirst.SetStringDefaultLength(200).InitTables(typeof(RowToColumn)); + Clean(); + InitData(); + Test5(); + Test6(); + } + public static void InitData() + { + var db = DbHelper.GetNewDb(); + var ls = new List(); + // 创建 Stopwatch 对象并开始计时 + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + + for (int i = 1; i <= 100 * 10000; i++) + { + ls.Add(new RowToColumn() + { + Id = Guid.NewGuid(), + Code = "A" + i % 1000, + Date = new DateTime(2023, i % 11 + 1, 1), + Date2 = new DateTime(2023, i % 11 + 1, i % 28 + 1, i % 24, i % 60, i % 60), + Val = i % 10, + T1 = i % 3 == 0 ? null : "T0", + T2 = i % 3 == 1 ? null : 3 + }); ; + if (i % 100000 == 0) + { + db.Fastest().PageSize(100000).BulkCopy(ls); + ls.Clear(); + } + } + + Task.Run(() => + { + }); + // 结束计时并获取经过的时间 + stopwatch.Stop(); + TimeSpan elapsedTime = stopwatch.Elapsed; + + Console.WriteLine("T0:" + elapsedTime); + } + public static void Clean() + { + var db = DbHelper.GetNewDb(); + db.DbMaintenance.TruncateTable(); + } + + public static void Test5() + { + var db = DbHelper.GetNewDb(); + // 创建 Stopwatch 对象并开始计时 + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + var s = new DateTime(2023, 2, 1); + var e = new DateTime(2023, 6, 1).AddMilliseconds(-1); + var ls = db.Queryable() + .Where(x => x.Date >= s && x.Date <= e) + .GroupBy(x => new { x.Code, x.Date, x.Val, x.T1, x.T2 }) + .Select(x => new { x.Code, x.Date, x.T1, x.T2, Val = SqlFunc.AggregateSum(x.Val) })//求和可以自动处理空值 + .ToPivotTable(it => it.Code, it => new { it.Date, it.T1, it.T2 }, it => it.Any() ? it.Sum(x => x.Val) : 0); + + // 结束计时并获取经过的时间 + stopwatch.Stop(); + TimeSpan elapsedTime = stopwatch.Elapsed; + + Console.WriteLine("T5:" + elapsedTime); + } + public static void Test6() + { + var db = DbHelper.GetNewDb(); + // 创建 Stopwatch 对象并开始计时 + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + var s = new DateTime(2023, 2, 1); + var e = new DateTime(2023, 6, 1).AddMilliseconds(-1); + var ls = db.Queryable() + .Where(x => x.Date >= s && x.Date <= e) + .GroupBy(x => new { x.Code, x.Date, x.Val, x.T1, x.T2 }) + .Select(x => new { x.Code, x.Date, x.T1, x.T2, Val = SqlFunc.AggregateSum(x.Val) })//求和可以自动处理空值 + .ToPivotList(it => it.Code, it => new { it.Date, it.T1, it.T2 }, it => it.Any() ? it.Sum(x => x.Val) : 0); + + // 结束计时并获取经过的时间 + stopwatch.Stop(); + TimeSpan elapsedTime = stopwatch.Elapsed; + + Console.WriteLine("T000:" + elapsedTime); + } + } + + [SugarTable("row_2_column")] + public class RowToColumn + { + [SugarColumn(IsPrimaryKey = true)] + public Guid Id { get; set; } + public DateTime Date { get; set; } + public DateTime Date2 { get; set; } + public string Code { get; set; } + public decimal? Val { get; set; } + [SugarColumn(ColumnName = "t_1", IsNullable = true)] + public string T1 { get; set; } + [SugarColumn(ColumnName = "t_2", IsNullable = true)] + public int? T2 { get; set; } + } +} diff --git a/Src/Asp.NetCore2/SqlSugar/Utilities/DataTableExtensions.cs b/Src/Asp.NetCore2/SqlSugar/Utilities/DataTableExtensions.cs index 08ee0da61..0065be726 100644 --- a/Src/Asp.NetCore2/SqlSugar/Utilities/DataTableExtensions.cs +++ b/Src/Asp.NetCore2/SqlSugar/Utilities/DataTableExtensions.cs @@ -2,13 +2,15 @@ using System.Collections.Generic; using System.Data; using System.Dynamic; +using System.IO; using System.Linq; using System.Linq.Expressions; +using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -namespace SqlSugar +namespace SqlSugar { internal static class DataTableExtensions { @@ -19,12 +21,13 @@ namespace SqlSugar Func, TData> dataSelector) { DataTable table = new DataTable(); - var rowName = ""; + var rowName = new List(); if (rowSelector.Body is MemberExpression) - rowName = ((MemberExpression)rowSelector.Body).Member.Name; + rowName.Add(((MemberExpression)rowSelector.Body).Member.Name); else - rowName =string.Join(UtilConstants.ReplaceKey, ((NewExpression)rowSelector.Body).Arguments.Select(it=>it as MemberExpression).Select(it=>it.Member.Name)); - table.Columns.Add(new DataColumn(rowName)); + rowName.AddRange(((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name)); + + table.Columns.AddRange(rowName.Select(x => new DataColumn(x)).ToArray()); var columns = source.Select(columnSelector).Distinct(); foreach (var column in columns) @@ -45,36 +48,23 @@ namespace SqlSugar { var dataRow = table.NewRow(); var items = row.Values.Cast().ToList(); - items.Insert(0, row.Key); + // 获取匿名对象的动态类型 + var anonymousType = row.Key.GetType(); + + // 获取匿名对象的所有属性 + var properties = anonymousType.GetProperties(); + + for (var i = 0; i < rowName.Count; i++) + { + items.Insert(i, properties[i].GetValue(row.Key, null)); + } dataRow.ItemArray = items.ToArray(); table.Rows.Add(dataRow); } - var firstName = table.Columns[0]?.ColumnName; - if (firstName.ObjToString().Contains(UtilConstants.ReplaceKey)) - { - int i = 0; - foreach (var item in Regex.Split(firstName,UtilConstants.ReplaceKey)) - { - i++; - table.Columns.Add(item); - table.Columns[item].SetOrdinal(i); - } - foreach (DataRow row in table.Rows) - { - var json =row[firstName]; - var list = json.ToString().TrimStart('{', ' ').TrimEnd('}', ' ') - .Split(new[] { ", " }, StringSplitOptions.None) - .Select(it => it.Split(new[] { " = " }, StringSplitOptions.None)).ToList(); - foreach (var item in Regex.Split(firstName, UtilConstants.ReplaceKey)) - { - var x = list.First(it => it.First().Trim() == item.Trim()); - row[item] =x[1] ; - } - } - table.Columns.Remove(firstName); - } + return table; } + public static List ToPivotList( this IEnumerable source, Func columnSelector, @@ -82,17 +72,17 @@ namespace SqlSugar Func, TData> dataSelector) { - var arr = new List(); + var arr = new List(); var cols = new List(); - var rowName = ""; + var rowName = new List(); if (rowSelector.Body is MemberExpression) - rowName = ((MemberExpression)rowSelector.Body).Member.Name; + rowName.Add(((MemberExpression)rowSelector.Body).Member.Name); else - rowName = "Group_"+string.Join("_", ((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name)); + rowName.AddRange(((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name)); + var columns = source.Select(columnSelector).Distinct(); - cols = (new[] { rowName }).Concat(columns.Select(x => x?.ToString())).ToList(); - + cols = rowName.Concat(columns.Select(x => x?.ToString())).ToList(); var rows = source.GroupBy(rowSelector.Compile()) .Select(rowGroup => new @@ -103,17 +93,26 @@ namespace SqlSugar c => c, r => columnSelector(r), (c, columnGroup) => dataSelector(columnGroup)) - }).ToList(); - + }); foreach (var row in rows) { var items = row.Values.Cast().ToList(); - items.Insert(0, row.Key); + + // 获取匿名对象的动态类型 + var anonymousType = row.Key.GetType(); + + // 获取匿名对象的所有属性 + var properties = anonymousType.GetProperties(); + + for (var i = 0; i < rowName.Count; i++) + { + items.Insert(i, properties[i].GetValue(row.Key, null)); + } var obj = GetAnonymousObject(cols, items); arr.Add(obj); } - return arr.ToList(); + return arr; } private static dynamic GetAnonymousObject(IEnumerable columns, IEnumerable values) { From 467020a04af0bed4c0749c78b6678bf468679db5 Mon Sep 17 00:00:00 2001 From: YHS Date: Fri, 5 Jan 2024 11:19:55 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=A7=A3=E5=86=B3.ToPivotTable(it=20=3D>?= =?UTF-8?q?=20it.day,=20it=20=3D>new{=20it.name},=20it=20=3D>=20it.Sum(x?= =?UTF-8?q?=20=3D>=20x.count))=E7=9A=84=E5=87=A0=E4=B8=AA=E9=97=AE?= =?UTF-8?q?=E9=A2=98=201=20it.name=20=E4=B8=BA=E7=A9=BA=E5=80=BC=E6=97=B6?= =?UTF-8?q?=E6=8A=9B=E5=87=BA=E5=BC=82=E5=B8=B8=E7=B4=A2=E5=BC=95=E8=B6=85?= =?UTF-8?q?=E5=87=BA=E7=95=8C=E5=80=BC=E5=BC=82=E5=B8=B8=202=20=E5=BD=93it?= =?UTF-8?q?.name=20=E7=9A=84=E5=80=BC=E4=B8=AD=20=E6=9C=89"T0=20=3D=20T1?= =?UTF-8?q?=20=3D=20T2"=E7=B1=BB=E4=BC=BC=E6=83=85=E5=86=B5=E6=98=AF?= =?UTF-8?q?=E4=BC=9A=E6=88=AA=E6=96=AD=E5=AD=97=E7=AC=A6=E4=B8=B2=EF=BC=8C?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E4=B8=BA"T0"=203=20=E6=8F=90=E5=8D=87?= =?UTF-8?q?=E8=BD=AC=E5=8C=96=E6=95=88=E7=8E=87=EF=BC=8C=E7=8E=B0=E5=9C=A8?= =?UTF-8?q?=E6=89=80=E8=8A=B1=E6=97=B6=E9=97=B4=E5=8F=AA=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E4=B9=8B=E5=89=8D=E7=9A=841/4=E5=B7=A6=E5=8F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SqlSugar/Utilities/DataTableExtensions.cs | 77 +++++++++---------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/Src/Asp.Net/SqlSugar/Utilities/DataTableExtensions.cs b/Src/Asp.Net/SqlSugar/Utilities/DataTableExtensions.cs index 08ee0da61..8582c05ec 100644 --- a/Src/Asp.Net/SqlSugar/Utilities/DataTableExtensions.cs +++ b/Src/Asp.Net/SqlSugar/Utilities/DataTableExtensions.cs @@ -8,7 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; -namespace SqlSugar +namespace SqlSugar { internal static class DataTableExtensions { @@ -19,12 +19,13 @@ namespace SqlSugar Func, TData> dataSelector) { DataTable table = new DataTable(); - var rowName = ""; + var rowName = new List(); if (rowSelector.Body is MemberExpression) - rowName = ((MemberExpression)rowSelector.Body).Member.Name; + rowName.Add(((MemberExpression)rowSelector.Body).Member.Name); else - rowName =string.Join(UtilConstants.ReplaceKey, ((NewExpression)rowSelector.Body).Arguments.Select(it=>it as MemberExpression).Select(it=>it.Member.Name)); - table.Columns.Add(new DataColumn(rowName)); + rowName.AddRange(((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name)); + + table.Columns.AddRange(rowName.Select(x => new DataColumn(x)).ToArray()); var columns = source.Select(columnSelector).Distinct(); foreach (var column in columns) @@ -45,36 +46,23 @@ namespace SqlSugar { var dataRow = table.NewRow(); var items = row.Values.Cast().ToList(); - items.Insert(0, row.Key); + // 获取匿名对象的动态类型 + var anonymousType = row.Key.GetType(); + + // 获取匿名对象的所有属性 + var properties = anonymousType.GetProperties(); + + for (var i = 0; i < rowName.Count; i++) + { + items.Insert(i, properties[i].GetValue(row.Key, null)); + } dataRow.ItemArray = items.ToArray(); table.Rows.Add(dataRow); } - var firstName = table.Columns[0]?.ColumnName; - if (firstName.ObjToString().Contains(UtilConstants.ReplaceKey)) - { - int i = 0; - foreach (var item in Regex.Split(firstName,UtilConstants.ReplaceKey)) - { - i++; - table.Columns.Add(item); - table.Columns[item].SetOrdinal(i); - } - foreach (DataRow row in table.Rows) - { - var json =row[firstName]; - var list = json.ToString().TrimStart('{', ' ').TrimEnd('}', ' ') - .Split(new[] { ", " }, StringSplitOptions.None) - .Select(it => it.Split(new[] { " = " }, StringSplitOptions.None)).ToList(); - foreach (var item in Regex.Split(firstName, UtilConstants.ReplaceKey)) - { - var x = list.First(it => it.First().Trim() == item.Trim()); - row[item] =x[1] ; - } - } - table.Columns.Remove(firstName); - } + return table; } + public static List ToPivotList( this IEnumerable source, Func columnSelector, @@ -82,17 +70,17 @@ namespace SqlSugar Func, TData> dataSelector) { - var arr = new List(); + var arr = new List(); var cols = new List(); - var rowName = ""; + var rowName = new List(); if (rowSelector.Body is MemberExpression) - rowName = ((MemberExpression)rowSelector.Body).Member.Name; + rowName.Add(((MemberExpression)rowSelector.Body).Member.Name); else - rowName = "Group_"+string.Join("_", ((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name)); + rowName.AddRange(((NewExpression)rowSelector.Body).Arguments.Select(it => it as MemberExpression).Select(it => it.Member.Name)); + var columns = source.Select(columnSelector).Distinct(); - cols = (new[] { rowName }).Concat(columns.Select(x => x?.ToString())).ToList(); - + cols = rowName.Concat(columns.Select(x => x?.ToString())).ToList(); var rows = source.GroupBy(rowSelector.Compile()) .Select(rowGroup => new @@ -103,17 +91,26 @@ namespace SqlSugar c => c, r => columnSelector(r), (c, columnGroup) => dataSelector(columnGroup)) - }).ToList(); - + }); foreach (var row in rows) { var items = row.Values.Cast().ToList(); - items.Insert(0, row.Key); + + // 获取匿名对象的动态类型 + var anonymousType = row.Key.GetType(); + + // 获取匿名对象的所有属性 + var properties = anonymousType.GetProperties(); + + for (var i = 0; i < rowName.Count; i++) + { + items.Insert(i, properties[i].GetValue(row.Key, null)); + } var obj = GetAnonymousObject(cols, items); arr.Add(obj); } - return arr.ToList(); + return arr; } private static dynamic GetAnonymousObject(IEnumerable columns, IEnumerable values) {