在下面的情况下我需要你的帮助(使用Pig Latin)。
我有以下格式的输入数据:
DATE,ERROR,COUNT
20110212,ORA-00600,9
20110212,ORA-03135,1
20110226,ORA-20000,1
20110305,ORA-03135,1
20110319,ORA-01555,1
20110319,ORA-03135,18
20110326,ORA-00600,1
20110409,ORA-00600,1
20110416,ORA-20000,1
20110423,ORA-01555,2
20110507,ORA-00600,1
20110507,ORA-01555,2
20110514,ORA-00600,1
20110514,ORA-03135,4
我正在寻找下面的输出。
DATE,ORA-00600,ORA-03135,ORA-20000....
20110212,9,1,0....
20110514,1,4,0...
20110416,0,0,1...
基本上,我希望透视输入数据;我无法使用嵌套的FOREACH(带过滤器),因为错误代码(如ORA-00600,ORA-03135 ..)不是常量,而是动态的。
请建议。
答案 0 :(得分:0)
关于SQL中的PIVOT功能有多少问题,我并不感到惊讶。我也有一些需要使用PIVOT结果的项目。电子表格是一个完美的例子(并且是企业IT世界的巨大需求)。
数据透视表非常棒,但如果您像我一样在动态制造环境中工作,它们通常会变得繁琐复杂。在这种领域中,需求总是主观的。并且可以让程序员从根部拉出他的头发。
正是由于这个原因,我决定在DataTable对象上创建一个扩展,它产生了一个我发现既快又有用的PIVOT表。
是的,我知道SQL版本,并且我知道有很多方法可以使SQL中的PIVOT更具动态性(用于更改列)。但我学会了保持简单。简单性就是稳定性,可用性,可扩展性和可扩展性。这些都是真正企业界的巨大优势。
我现在和你分享这个,希望你能修改它以满足你的需求。它是动态的,非常快......最好的SIMPLE。
/// <summary>
/// Creates a PIVOT table based on values in existing table
/// </summary>
/// <param name="PKey">Field used as PIVOT tables Primary (row) Key.</param>
/// <param name="FKey">Field used to create unique column names in PIVOT table.</param>
/// <param name="VKey">Field used as the value for each associated column in a PIVOT table record.</param>
/// <returns>DataTable</returns>
public static DataTable Pivot(this DataTable tbl, string PKey, string FKey, string VKey)
{
DataTable retVal = null;
DataTable keyTbl = null;
DataTable fldTbl = null;
DataColumn dc = null;
DataRow newRow = null;
Type pkType = null;
Type valType = null;
string strPkeyFilter = null;
string prevFilter = null;
try
{
// Get previous filter (save)
prevFilter = tbl.DefaultView.RowFilter;
if (tbl.Rows.Count > 0)
{
// Get unique Primary Keys and Field Names
keyTbl = tbl.DefaultView.ToTable(true, PKey);
fldTbl = tbl.DefaultView.ToTable(true, FKey);
if (fldTbl.Rows.Count > 0)
{
// Get Primary Key data type and create column on Pivot table.
pkType = tbl.Columns[PKey].DataType;
retVal = new DataTable(tbl.TableName);
retVal.Columns.Add(new DataColumn(PKey, pkType));
retVal.PrimaryKey = new DataColumn[] { retVal.Columns[PKey] };
// Get VALUE columns data type
valType = tbl.Columns[VKey].DataType;
// Create Primary Key filter
strPkeyFilter = "{0} = {1}";
if(pkType.Equals(typeof(string)))
strPkeyFilter = "{0} = '{1}'";
foreach (DataRow dr in fldTbl.Rows)
{
// Create additional rows in Pivot table based on unique Field Names
dc = new DataColumn(Convert.ToString(dr[FKey]), valType);
dc.AllowDBNull = true;
dc.DefaultValue = DBNull.Value;
retVal.Columns.Add(dc);
}
// Iterate through Primary Key collection
foreach (DataRow dr in keyTbl.Rows)
{
// Set Primary Key row filter on base table
tbl.DefaultView.RowFilter = string.Format(strPkeyFilter, PKey, dr[PKey]);
if (tbl.DefaultView.Count > 0)
{
// Create new row on Pivot table and set Primary Key
newRow = retVal.NewRow();
newRow[PKey] = dr[PKey];
// Iterate through records and find VALUE for each FIELD column
foreach (DataRowView drv in tbl.DefaultView)
newRow[Convert.ToString(drv[FKey])] = drv[VKey];
retVal.Rows.Add(newRow);
}
}
// Return previous row filter on base table
tbl.DefaultView.RowFilter = prevFilter;
// Commit chages to Pivot table (if any)
retVal.AcceptChanges();
}
}
}
catch (Exception)
{
throw;
}
finally
{
if (keyTbl != null)
keyTbl.Dispose();
if (fldTbl != null)
fldTbl.Dispose();
}
return retVal;
}
用法很简单,因为它是DataTable对象的扩展方法:
DataTable dt = myTbl.Pivot("DOC_ID", "UI_FIELD", "UI_VALUE");
如果 myTbl 的布局如下:
DOC_ID | ENTRY_DATE | UI_FIELD | UI_CAPTION | UI_VALUE
----------------------------------------------------------------
1 01/01/2015 EMPL_NAME Empl. Name John Doe
1 01/01/2015 EMPL_PHONE Empl. Phone 801-555-1212
1 01/01/2015 EMPL_MNGR Empl. Mangr. Jane Doe
它将返回:
DOC_ID | ENPL_NAME | EMPL_PHONE | EMPL_MNGR
-------------------------------------------------
1 John Doe 801-555-1212 Jane Doe
在垂直行中布置UI条目数据的好处(在制造环境中无论如何)是为了更好地适应UI字段添加或减少..这种情况很多!因为您要做的最后一件事是修改数据模式。特别是当大约一百个(已知和未知)应用程序也在使用它时。
无论如何,以及它的价值,我希望这会让你朝着理想的方向前进。我经常使用它。