C#/DataTable

[C#/.Net] SQL Group by Sum 효과 메소드

Fly_Mir 2016. 1. 8. 13:42
Mir의 운영환경
본체DeskTop
O SWindows 7 Ultimate K
ApplicationVisualStudio2015
.NetFramework Ver 4.0

C#으로 DataTable의 내용을 Group by Sum 해보자.

LINQ를 공부하는 중이였는데..

이번 프로젝트에서 LINQ를 쓰지말라고 하네요. (다른 사람이 헷갈린다고..)

뭐 음... 네 그래서 LINQ를 쓰지않고 가져온 데이터를 Group by Sum하는 함수를 만들었습니다.

(사실은 공부중이여서 LINQ로는 어찌하는지 모릅니다. 사용해 보고 싶었는데.. ㅠ)

해당 함수는 아래와 같이 작동합니다.

기본 데이터

141-1

부서별 월급 합계

141-2

그룹별(전체) 월급,보너스 합계

141-3

팀별 보너스 합계

141-4

부서,팀 별 월급,보너스 합계

141-5


아래 GetGroupBySum()메소드에 DataTable과 집계(Sum)을 할 컬럼들, 그룹(Group) 컬럼을 parameter로 넣어주면 됩니다.

마지막 parameter로 Boolean값을 받는데

이건 Parameter로 넣은 DataTable과 컬럼구조를 똑같이 가져올것이냐

아니면 위 Parameter로 넣은 컬럼만 가져올것이냐 묻는것입니다.

(이건 넣은 이유가 따로 있습니다. 궁금하시면 연관글에서 부서,팀별 합계 데이터 삽입하기를 보시면 됩니다.)

많은 도움되었으면 좋겠습니다.

    using System;
    using System.Data;
    using System.Windows.Forms;
     
    namespace GroupbySum
    {
        public partial class GroupBySumTest : Form
        {
            public GroupBySumTest()
            {
                InitializeComponent();
     
                //기본 데이터
                dataGridView1.DataSource = Create_Sample();
                //부서별 월급 합계
                dataGridView1.DataSource = GetGroupBySum(Create_Sample(), new string[] { "Salary" }
                                                                          , new string[] { "Dept" }, false);
                //그룹별(전체) 월급,보너스 합계
                dataGridView1.DataSource = GetGroupBySum(Create_Sample(), new string[] { "Salary", "Bonus" }
                                                                          , new string[] { "Group" }, false);
                //팀별 보너스 합계
                dataGridView1.DataSource = GetGroupBySum(Create_Sample(), new string[] { "Bonus" }
                                                                          , new string[] { "Team" }, false);
                //부서,팀 별 월급,보너스 합계
                dataGridView1.DataSource = GetGroupBySum(Create_Sample(), new string[] { "Salary", "Bonus" }
                                                                          , new string[] { "Dept", "Team" }, false);
            }
     
     
            DataTable Create_Sample()
            {
                //DataTable 생성 
                DataTable dt = new DataTable { TableName = "TestTbl" };
                //Columns 생성 
                dt.Columns.AddRange(new DataColumn[] {
                new DataColumn { ColumnName = "Group",      Caption = "그룹",        DataType = typeof(string)   }
              , new DataColumn { ColumnName = "Dept",       Caption = "부서",        DataType = typeof(string)   }
              , new DataColumn { ColumnName = "Team",       Caption = "팀",          DataType = typeof(string)   }
              , new DataColumn { ColumnName = "User",       Caption = "사원",        DataType = typeof(string)   }
              , new DataColumn { ColumnName = "Salary",     Caption = "월급",        DataType = typeof(int)      }
              , new DataColumn { ColumnName = "Bonus",      Caption = "보너스",      DataType = typeof(string)   }
                });
     
                DataRow dr = dt.NewRow();
                dt.Rows.Add(new object[] { "기획그룹", "기획부", "기획팀", "기획1" ,100 ,"10" });
                dt.Rows.Add(new object[] { "기획그룹", "기획부", "기획팀", "기획2", 200, "20" });
     
                dt.Rows.Add(new object[] { "기획그룹", "기획부", "보조", "기획보조1", 10, "20" });
                dt.Rows.Add(new object[] { "기획그룹", "기획부", "보조", "기획보조2", 20, "20" });
                dt.Rows.Add(new object[] { "기획그룹", "기획부", "보조", "기획보조3", 30, "20" });
     
                dt.Rows.Add(new object[] { "기획그룹", "생산부", "생산팀", "생산1", 110, "10" });
                dt.Rows.Add(new object[] { "기획그룹", "생산부", "생산팀", "생산2", 220, "20" });
                dt.Rows.Add(new object[] { "기획그룹", "생산부", "생산팀", "생산3", 330, "30" });
     
                dt.Rows.Add(new object[] { "기획그룹", "생산부", "보조", "생산보조1", 11, "10" });
                dt.Rows.Add(new object[] { "기획그룹", "생산부", "보조", "생산보조2", 22, "20" });
                dt.Rows.Add(new object[] { "기획그룹", "생산부", "보조", "생산보조3", 33, "30" });
     
                return dt;
            }
     
            /// <summary>
            /// DataTable의 Data로 SQL Group by Sum 효과 메소드
            /// </summary>
            /// <param name="dt">Data
            /// <param name="sumColumnNames">Sum Columns
            /// <param name="groupByColumnNames">Group Columns
            /// <param name="reAllColumn">리턴시 기존 DataTable의 컬럼을 모두 받을것인지
            /// <para>false시 Sum Column과 Group Column만 리턴</para>
            /// /param>
            /// <returns></returns>
            private DataTable GetGroupBySum(DataTable dt, string[] sumColumnNames
                                          , string[] groupByColumnNames, bool reAllColumn)
            {
     
                DataTable dt_Return = null;
     
                try
                {
                    //Check datatable
                    if (dt == null || dt.Rows.Count < 1) { return dt; }
                    //Check sum columns
                    if (sumColumnNames == null || sumColumnNames.Length < 1) { return dt; }
                    //Check group columns
                    if (groupByColumnNames == null || groupByColumnNames.Length < 1) { return dt; }
     
                    //Create return datatable
                    dt_Return = dt.DefaultView.ToTable(true, groupByColumnNames);
     
                    //Set return Columns
                    if (reAllColumn)
                    {
                        for (int i = 0; i < dt.Columns.Count; i++)
                        {
                            if (!dt_Return.Columns.Contains(dt.Columns[i].ColumnName))
                            {
                                DataColumn dc = new DataColumn(dt.Columns[i].ColumnName, dt.Columns[i].DataType);
                                dt_Return.Columns.Add(dc);
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < sumColumnNames.Length; i++)
                        {
                            if (dt.Columns.Contains(sumColumnNames[i]))
                            {
                                DataColumn dc = new DataColumn(sumColumnNames[i]
                                                , dt.Columns[sumColumnNames[i]].DataType);
                                dt_Return.Columns.Add(dc);
                            }
                        }
                    }
     
                    //Summary Rows
                    for (int i = 0; i < dt_Return.Rows.Count; i++)
                    {
                        var sQuery = " 1=1 ";
     
                        foreach (var col in groupByColumnNames)
                        {
                            sQuery += "AND " + col + " = '" + dt_Return.Rows[i][col].ToString() + "'";
                        }
                        DataRow[] drs = dt.Select("(" + sQuery + ")");
     
                        foreach (var dr in drs)
                        {
                            foreach (var col in sumColumnNames)
                            {
                                int sum, val = 0;
                                int.TryParse(dt_Return.Rows[i][col].ToString(), out sum);
                                int.TryParse(dr[col].ToString(), out val);
                                dt_Return.Rows[i][col] = sum + val;
                            }
                        }
                    }
                }
                catch (Exception ex) { }
     
                return dt_Return;
            }
        }
    }

Ps. 혹시 Exception이 일어나거나 좀 더 좋은 방법이 있으면 공유 부탁드립니다.