行列转换

一.概述

1、  行转列

例如将下表(RowToColumn)

Student

Course

Score

李四

语文

78

李四

数学

66

张珊

语文

67

张珊

数学

79

转成(ColumnToRow)

Student

语文

数学

李四

78

66

张珊

67

79

  

 2.列转行:上述过程反过来

 

二.Sqlserver中的两种转换方式

  1. 行转列

[1] Pivot

   语法:    

Table_Source

Pivot (

聚合函数(value_column)  For  pivot_column in (<column_list>)

 

   例:

     select Student,[语文],[数学] from   RowToColumn  pivot ( max(score) for Course in ([语文],[数学]) ) tb

   查询结果如上表ColumnToRow

 

[2] Case  when

   例:

 select student,max(case Course when '语文' then Score else 0 end) as [语文]

,max(case Course when '数学' then Score else 0 end) as [数学] from RowToColumn group by student

查询结果如上表ColumnToRow

 

  1. 列转行

[1]  UnPivot

    语法:      

Table_Source

UnPivot(

value_column     for pivot_column

in(<column_list>)

) 

 

例:

select student ,Course,Score from ColumnToRow unpivot (Score for Course in([语文],[数学])) t

[2]  Union

例:

select *  from(

select student ,Course='语文',Score=[语文] from ColumnToRow

union

select student ,Course='数学',Score=[数学] from ColumnToRow

) t

 

三.在C#中实现行列转换

  1. 行转列         
 /// <summary>
        /// 行转列
        /// </summary>
        /// <param name="sourseDT">源datatable</param>
        /// <param name="column">作为转换依据的列,即将此列中的行值转换为列</param>
        /// <param name="Value">除column外的另一列,新列的列值将从此列获取</param>
        /// <returns></returns>
        public DataTable RowToColumn(DataTable sourseDT, string column, string ValueCol)
        {
            string sortCol = ""; string[] sortCols = new string[sourseDT.Columns.Count];
            DataTable result = new DataTable(); DataTable dtTemp = new DataTable();
            string groupCol = ""; int groupColNum = 0;
            foreach (DataColumn item in sourseDT.Columns)//添加除column、ValueCol外原来的列
            {
                if (item.Caption == column || item.Caption == ValueCol) continue;
                result.Columns.Add(item.Caption);
                if (groupCol.Length > 0) groupCol += ",";
                groupCol += item.Caption; groupColNum++;//标记除column、ValueCol外原来的列
            }
            sortCol = groupCol + "," + column + "," + ValueCol;
            sortCols = sortCol.Split(',');
            sourseDT = sourseDT.DefaultView.ToTable(false, sortCols);//重新排序sourseDT:除column、ValueCol外原来的列排在前面
            dtTemp = sourseDT.DefaultView.ToTable(true, column);//获取column列无重复数据
            foreach (DataRow item in dtTemp.Rows)//column列无重复列值全转为列
            {
                  result.Columns.Add(item[column].ToString());
            }
            dtTemp = sourseDT.DefaultView.ToTable(true, groupCol.Split(','));//依据groupCol,得到分组分组依据行
            DataTable dtTemp1 = new DataTable();
            foreach (DataRow item in dtTemp.Rows)
            {
                object[] newRow = new object[result.Columns.Count];
                string tempfilter="";
                foreach (DataColumn item1 in dtTemp.Columns)//根据dtTemp中的一条记录,从sourseDT筛选出一组数据
                {
                    if (tempfilter.Length > 0) tempfilter += " and ";
                   tempfilter+=item1.ColumnName+"='"+item[item1].ToString()+"'";
                }
                sourseDT.DefaultView.RowFilter=tempfilter;
                dtTemp1 = sourseDT.DefaultView.ToTable();//筛选结果,新表的一行记录将从这个dtTemp1里取
                foreach (DataRow row in dtTemp1.Rows)
                {
                    for (int i = 0; i < result.Columns.Count; i++)
                    {
                        if (i < groupColNum)
                        {
                            newRow[i] = row[i];
                        }
                        else 
                        if (row[column].ToString() == result.Columns[i].ColumnName)
                        {
                          newRow[i] = row[ValueCol].ToString(); break;
                        }
                    }
                }
                result.Rows.Add(newRow);
            }        
            return result;
        }
View Code

     

      2.列转行     

        /// <summary>
        /// 列转行
        /// </summary>
        /// <param name="sourseDT">源datatable</param>
        /// <param name="columns">将要被转成行的列</param>
        /// <param name="colName">新表中存放的列名的列</param>
        /// <param name="colValueName">新表中存放的列值的列</param>
        /// <returns></returns>
        public DataTable ColumnToRow(DataTable sourseDT,string[] columns ,string colName,string colValueName)
        {
            DataTable result = new DataTable(); string sortCol = ""; string[] sortCols = new string[sourseDT.Columns.Count];
            foreach (DataColumn item in sourseDT.Columns)//添加全部除columns列以外的列
            { 
              
                if (columns.Contains(item.ColumnName)) continue;
                result.Columns.Add(item.ColumnName);
                if (sortCol.Length > 0) sortCol += ",";
                sortCol += item.ColumnName;
            }
            sortCols = sortCol.Split(',').Union(columns).ToArray();
            sourseDT = sourseDT.DefaultView.ToTable(false, sortCols);

            result.Columns.Add(colName);  result.Columns.Add(colValueName);
            foreach (DataRow row in sourseDT.Rows)
            {
                object[] newRow = new object[result.Columns.Count];
                for (int i=0;i<sourseDT.Columns.Count;i++)
                {
                    if (!columns.Contains(sourseDT.Columns[i].ColumnName))
                    {
                        newRow[i] = row[i];
                    }
                    else
                    {
                        newRow[newRow.Length-2] = sourseDT.Columns[i].ColumnName;//存列名
                        newRow[newRow.Length-1] = row[i];//存列值
                        result.Rows.Add(newRow);
                    }
                }
            }
            return result;
        }
View Code

 

 

 

 

 

posted @ 2013-05-23 23:28  无上修罗  阅读(179)  评论(0)    收藏  举报