zoukankan      html  css  js  c++  java
  • 还是行列转换

    因为项目原因,需要对关系数据表查询并输出交叉表,这个问题网上资料很多,但基本思路雷同,通过拼sql,用case。。when生成表头。邹建有一个很好的过程,输入简单的参数就可以转换和汇总求和。但是存储过程方式受具体数据库影响,不易扩展。所以想有个方法对内存表进行处理,生成交叉表。网上找了很久,终于发现了老外的一个方法,不敢独享,共同学习。(求和有问题,修改了一下,可以多加一列”合计”)

    /// <summary>
            /// 行列转换数据表
            /// </summary>
            /// <param name="table">要转换的源表</param>
            /// <param name="columnX">显示在行的字段,类似mdx中rows</param>
            /// <param name="columnY">显示在列的字段,类似mdx中columns</param>
            /// <param name="columnZ">指标名</param>
            /// <param name="nullValue">空值表示方式</param>
            /// <param name="sumxValues">是否取x轴合计</param>

            /// <param name="sumyValues">是否取y轴合计</param> 
            /// <returns></returns>
           

    public DataTable GetInversedDataTable(DataTable table, string columnX, string columnY, string columnZ, string nullValue, bool XsumValues,bool YsumValues)
            {
                //Create a DataTable to Return
                DataTable returnTable = new DataTable();

                if (string.IsNullOrEmpty(columnX))
                {
                    columnX = table.Columns[0].ColumnName;
                }

                //Add a Column at the beginning of the table
                returnTable.Columns.Add(columnY);
                //Read all DISTINCT values from columnX Column in the provided DataTale
                List<string> columnXValues = new List<string>();

                foreach (DataRow dr in table.Rows)
                {

                    string columnXTemp = dr[columnX].ToString();
                    if (!columnXValues.Contains(columnXTemp))
                    {
                        //Read each row value, if it's different from others provided, add to the list of values and creates a new Column with its value.
                        columnXValues.Add(columnXTemp);
                        returnTable.Columns.Add(columnXTemp);
                    }
                }
            //如果有合计列则增加合计列
                if (XsumValues)
                {
                    columnXValues.Add("合计");
                    returnTable.Columns.Add("合计",Type.GetType("System.Decimal"));
                }
                //Verify if Y and Z Axis columns re provided
                if (!string.IsNullOrEmpty(columnY) && !string.IsNullOrEmpty(columnZ))
                {
                    //Read DISTINCT Values for Y Axis Column
                    List<string> columnYValues = new List<string>();

                    foreach (DataRow dr in table.Rows)
                    {
                        if (!columnYValues.Contains(dr[columnY].ToString()))
                        {
                            columnYValues.Add(dr[columnY].ToString());
                        }
                    }
                    //Loop all Column Y Distinct Value
                    foreach (string columnYValue in columnYValues)
                    {
                        decimal sumx=decimal.Zero;
                        //Creates a new Row
                        DataRow drReturn = returnTable.NewRow();
                        drReturn[0] = columnYValue;
                        //foreach column Y value, The rows are selected distincted
                        DataRow[] rows = table.Select((columnY + "='") + columnYValue + "'");

                        //Read each row to fill the DataTable
                        foreach (DataRow dr in rows)
                        {
                            string rowColumnTitle = dr[columnX].ToString();

                            //Read each column to fill the DataTable
                            foreach (DataColumn dc in returnTable.Columns)
                            {
                                if (dc.ColumnName == rowColumnTitle)
                                {
                                    //If Sum of Values is True it try to perform a Sum
                                    //If sum is not possible due to value types, the value displayed is the last one read
                                        drReturn[rowColumnTitle] = dr[columnZ];
                                    sumx+=decimal.Parse(dr[columnZ].ToString());
                                }
                            }
                        }
                        if(XsumValues)
                        {
                            drReturn["合计"] = sumx;
                        }
                        returnTable.Rows.Add(drReturn);
                    }

                }
                else
                {
                    throw new Exception("The columns to perform inversion are not provided");
                }
            //如果行总计则做汇总计算
                if (YsumValues)
                {
                    DataRow dr=returnTable.NewRow();
                    dr[0] = "总计";
                    for (int i = 1; i < returnTable.Columns.Count; i++)
                    {
                        for (int j = 0; j < returnTable.Rows.Count; j++)
                        {
                            decimal result1=decimal.Zero;
                            decimal.TryParse(dr[i].ToString(), out result1);
                            decimal result2=decimal.Zero;
                            if (decimal.TryParse(returnTable.Rows[j][i].ToString(), out result2))
                                dr[i] = (result1 + result2).ToString();
                        }
                    }
                    returnTable.Rows.Add(dr);
                }
                //if a nullValue is provided, fill the datable with it
                if (!string.IsNullOrEmpty(nullValue))
                {
                    foreach (DataRow dr in returnTable.Rows)
                    {
                        foreach (DataColumn dc in returnTable.Columns)
                        {
                            if (string.IsNullOrEmpty(dr[dc.ColumnName].ToString()))
                            {
                                dr[dc.ColumnName] = nullValue;
                            }
                        }
                    }
                }

                return returnTable;
            }

    代码蛮多,不知道用linq to dataset有没有简洁的写法,期待linq达人!

  • 相关阅读:
    GCC 命令行详解 -L 指定库的路径 -l 指定需连接的库名(转载)
    vector,list,deque容器的迭代器简单介绍
    自己动手实现简单的Vector
    浅析STL allocator
    STL中的Traits编程技法
    模板类的全特化、偏特化
    自己动手实现智能指针auto_ptr
    各种排序算法的总结和比较(转)
    (CVE-2017-7269 ) IIS6.0实现远程控制
    (CVE-2016-5195)脏牛本地提权
  • 原文地址:https://www.cnblogs.com/malingbo/p/1621057.html
Copyright © 2011-2022 走看看