将平面查询转换为二维 table
Turn flat query into 2D table
我有一个数据库 table,其中每一行都有(除其他外)日期、产品和数量字段:
Date Prod Qty
06/01/2018 ABC 10
06/02/2018 ABC 5
06/03/2018 ABC 3
...
06/01/2018 DEF 2
06/02/2018 DEF 8
06/03/2018 DEF 11
...
06/01/2018 GHI 1
我想输出按日期和产品分组的 2D table:
ABC DEF GHI
06/01/2018 10 2 1
06/02/2018 5 8 2
06/03/2018 3 11 4
我可以看到一种丑陋且非 LINQ-y 的方式来执行此操作(找到不同的日期和产品列表,制作一个尺寸与这些列表匹配的二维数组,手动遍历列表以找到与那行和那列。)但是还有更优雅的东西吗?
产品数量很多,因此手动加入一堆查询似乎不可行。
像下面的代码一样创建一个枢轴table:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Prod", typeof(string));
dt.Columns.Add("Qty", typeof(int));
dt.Rows.Add(new object[] {DateTime.Parse("06/01/2018"), "ABC", 10});
dt.Rows.Add(new object[] {DateTime.Parse("06/02/2018"), "ABC", 5});
dt.Rows.Add(new object[] {DateTime.Parse("06/03/2018"), "ABC", 3});
dt.Rows.Add(new object[] {DateTime.Parse("06/01/2018"), "DEF", 2});
dt.Rows.Add(new object[] {DateTime.Parse("06/02/2018"), "DEF", 8});
dt.Rows.Add(new object[] {DateTime.Parse("06/03/2018"), "DEF", 11});
dt.Rows.Add(new object[] {DateTime.Parse("06/01/2018"), "GHI", 1});
string[] uniqueProducts = dt.AsEnumerable().Select(x => x.Field<string>("Prod")).OrderBy(x => x).Distinct().ToArray();
DataTable pivot = new DataTable();
pivot.Columns.Add("Date", typeof(DateTime));
foreach (string prod in uniqueProducts)
{
pivot.Columns.Add(prod, typeof(int));
}
var groups = dt.AsEnumerable().OrderBy(x => x.Field<DateTime>("Date")).GroupBy(x => x.Field<DateTime>("Date").Date).ToList();
foreach(var group in groups)
{
DataRow newRow = pivot.Rows.Add();
newRow["Date"] = group.Key;
foreach (DataRow row in group)
{
newRow[row.Field<string>("Prod")] = row.Field<int>("Qty");
}
}
}
}
}
我有一个数据库 table,其中每一行都有(除其他外)日期、产品和数量字段:
Date Prod Qty
06/01/2018 ABC 10
06/02/2018 ABC 5
06/03/2018 ABC 3
...
06/01/2018 DEF 2
06/02/2018 DEF 8
06/03/2018 DEF 11
...
06/01/2018 GHI 1
我想输出按日期和产品分组的 2D table:
ABC DEF GHI
06/01/2018 10 2 1
06/02/2018 5 8 2
06/03/2018 3 11 4
我可以看到一种丑陋且非 LINQ-y 的方式来执行此操作(找到不同的日期和产品列表,制作一个尺寸与这些列表匹配的二维数组,手动遍历列表以找到与那行和那列。)但是还有更优雅的东西吗?
产品数量很多,因此手动加入一堆查询似乎不可行。
像下面的代码一样创建一个枢轴table:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt.Columns.Add("Date", typeof(DateTime));
dt.Columns.Add("Prod", typeof(string));
dt.Columns.Add("Qty", typeof(int));
dt.Rows.Add(new object[] {DateTime.Parse("06/01/2018"), "ABC", 10});
dt.Rows.Add(new object[] {DateTime.Parse("06/02/2018"), "ABC", 5});
dt.Rows.Add(new object[] {DateTime.Parse("06/03/2018"), "ABC", 3});
dt.Rows.Add(new object[] {DateTime.Parse("06/01/2018"), "DEF", 2});
dt.Rows.Add(new object[] {DateTime.Parse("06/02/2018"), "DEF", 8});
dt.Rows.Add(new object[] {DateTime.Parse("06/03/2018"), "DEF", 11});
dt.Rows.Add(new object[] {DateTime.Parse("06/01/2018"), "GHI", 1});
string[] uniqueProducts = dt.AsEnumerable().Select(x => x.Field<string>("Prod")).OrderBy(x => x).Distinct().ToArray();
DataTable pivot = new DataTable();
pivot.Columns.Add("Date", typeof(DateTime));
foreach (string prod in uniqueProducts)
{
pivot.Columns.Add(prod, typeof(int));
}
var groups = dt.AsEnumerable().OrderBy(x => x.Field<DateTime>("Date")).GroupBy(x => x.Field<DateTime>("Date").Date).ToList();
foreach(var group in groups)
{
DataRow newRow = pivot.Rows.Add();
newRow["Date"] = group.Key;
foreach (DataRow row in group)
{
newRow[row.Field<string>("Prod")] = row.Field<int>("Qty");
}
}
}
}
}