计算数据列中每个distict项的出现次数

时间:2015-09-04 13:23:54

标签: c#

我正在使用C#ConoleApplication。

我有ODBC DSN连接,我带入Datatable。 第一列是#34;帐号#"。

示例:

帐号------------ |

AA1 ------------------- |

AA1 ------------------- |

AA2 ------------------- |

AA3 ------------------- |

------------------- AA1 |

AA4 ------------------- |

AA2 ------------------- |

我正在尝试研究如何给出以下结果。 我认为它将被整合到一个新的数据表中,但我不能使任何代码工作,我尝试过。

帐号------------ | OCCURENCES

AA1 ------------------- | 3

AA2 ------------------- | 2

AA3 ------------------- | 1

AA4 ------------------- | 1

请问我该怎么做?

8 个答案:

答案 0 :(得分:6)

您可以使用Linq-To-DataTableEnumerable.GroupBy

var accountGroups = table.AsEnumerable()
    .GroupBy(row => row.Field<String>("Account#"))
    .Select(grp => new { Account = grp.Key, Count = grp.Count() });

如果您需要新的DataTable

var tblAccCounts = new DataTable();
tblAccCounts.Columns.Add("Account#");
tblAccCounts.Columns.Add("Count", typeof(int));

foreach(var grp in accountGroups)
    tblAccCounts.Rows.Add(grp.Account, grp.Count);

答案 1 :(得分:1)

对于LINQ,DataTable有点奇怪,但它可以做到。关键是转换DataTable.Rows返回的DataRowCollection。

var results = DataTable.Rows
    .Cast<DataRow>()
    .GroupBy(row => row.Field<string>(0))
    .Select(g => new { Account = g.Key, Occurrences = g.Count()});

将结果导入新的DataTable有点复杂,因为您需要手动创建表。

DataTable newTable = new DataTable();
newTable.Columns.Add(new DataColumn("Account#", typeof(string)));
newTable.Columns.Add(new DataColumn("Occurrences", typeof(int)));

foreach(var result in results)
{
    var row = newTable.Rows.NewRow();
    row[0] = result.Account;
    row[1] = result.Occurrences;
    newTable.Rows.Add(row);
}

编辑:蒂姆的解决方案也有效:)

答案 2 :(得分:0)

未经测试,但使用linq会让您的生活更轻松

using System.Linq;

dynamic amounts = dataTable
    .AsQueryable()
    .GroupBy(item => item.AccountNumber)
    .Select(list => new{ AccountNumber: list.Key, Amount: list.Count() }).ToList();

答案 3 :(得分:0)

也许这会奏效。刚在我的数据库上试过它。

按帐户从表格组中选择帐户,计数(帐户);

答案 4 :(得分:0)

你可以试试这个:

class Program
    {
        static void Main(string[] args)
        {
            testClass tc = new testClass();
            DataTable dt = tc.getTestData();

            for(int i = 0; i < dt.Rows.Count; i++)
            {
                Console.WriteLine("Account No {0} Occurence {1}", dt.Rows[i]["ACCNO"].ToString(), dt.Rows[i]["Occurence"].ToString());
            }
        }
    }

    class testClass
    {
        public string AccountNo { get; set; }

        private SqlConnection Conn;

        private void TestConnect()
        {
            string strConn = "Data source = .\\SQLEXPRESS2012; Initial catalog = TEST; Integrated security = SSPI;";
            Conn = new SqlConnection(strConn);
        }

        public DataTable getTestData()
        {
            TestConnect();
            string cmdStr = "SELECT ACCNO, COUNT(XYZ.ACCNO) AS 'Occurence' FROM XYZ GROUP BY ACCNO;";
            SqlCommand cmd = new SqlCommand(cmdStr, Conn);
            SqlDataAdapter sda = new SqlDataAdapter(cmd);
            DataTable dt = new DataTable();
            try
            {
                Conn.Open();
                sda.Fill(dt);
            }
            catch (SqlException se)
            {
                Console.WriteLine("Error occured {0}", se.ToString());
            }
            finally
            {
                Conn.Close();
            }

            return dt;
        }
    }

答案 5 :(得分:0)

  

简单可靠的解决方案

我认为这就是你想要的。

示例代码

// Create Results DataTable

DataTable ResultsDataTable = new DataTable();
ResultsDataTable.Columns.Add("Account#"); // Columns default to System.string
ResultsDataTable.Columns.Add("Occurances", Type.GetType("System.Int32"));

ResultsDataTable.AcceptChanges(); //This asserts any changes to your table structure.

// Populate Results DataTable

foreach (DataRow SourceDataRow in SourceDataTable.Rows)
{
    string AccountNumber = SourceDataRow["Account#"].ToString();

    bool IsPresent = false;

    foreach(DataRow ResultsDataRow in ResultsDataTable.Rows)
    {
        if(ResultsDataRow["Account#"].ToString() == AccountNumber)
        {
            ResultsDataRow["Occurances"] = ((int)ResultsDataRow["Occurances"]) + 1; //Row exists for this account number, so increment the occurances value

            IsPresent = true;

            break;

        }

    }

    if (!IsPresent)
    { 
        // There isn't a row for this Account number, so create one and set it to one.

        DataRow NewResultsRow = ResultsDataTable.NewRow();

        NewResultsRow["Account#"] = AccountNumber;

        NewResultsRow["Occurances"] = 1;

        ResultsDataTable.Rows.Add(NewResultsRow);

        ResultsDataTable.AcceptChanges();

    }

}

ResultsDataTable.AcceptChanges();

关于此示例的说明

我不知道你的源DataTable被调用了什么,所以我称之为SourceDataTable。

同样,我创建了一个名为ResultsDataTable的结果数据表。

这大约是最近的Linq等值的两倍

这涵盖了操作DataTables的大多数常用方法,因此它应该能够帮助您在将来自行解决类似的问题。

我希望它有所帮助并祝你好运。

答案 6 :(得分:0)

最佳实践方法当然是采用其他答案所示的 Linq 框架。

但是,如果您想要一种更“零原则”的方法,为您提供列中每个项目的计数,我会提出以下建议。请注意,此方法实际上更灵活一些,因为它返回该列中每个项目 的计数的字典或“地图”,而不仅仅是您要查找的那个。然后您需要做的就是在地图上查询您的特定项目。

private DataTable dt;

...

private Dictionary<string, int> countColumnOccurances(int columnIndex)
{
    //Make a unique list of Items for the column of interest
    string indexName = dt.Columns[columnIndex].ColumnName;
    DataView view = new DataView(dt);
    DataTable distinctColumnDT = view.ToTable(true, dt.Columns[columnIndex].ColumnName);
    List<String> listOfDistinctItems = new List<String>();
    foreach (DataRow r in distinctColumnDT.Rows)
    {
        listOfDistinctItems.Add(r[indexName].ToString());
    }
    //Associate each of these items with a count
    var itemsAndTheirCount = new Dictionary<String, int>();
    int count = 0;
    foreach (var l in listOfDistinctItems)
    {
        foreach (DataRow r in dt.Rows)
        {
            if (l == r[indexName].ToString())
            {
                count++;
            }
        }
        itemsAndTheirCount.Add(l, count);
        count = 0;
    }
    return itemsAndTheirCount;
}

包括冗长和冗长,以便您可以遵循逻辑,但是,您可以轻松减少行数。

答案 7 :(得分:-1)

您正在使用SqlServer?如果是这样,你可以在bd上这样做:

SELECT Account#, Count(*) FROM [Table] GROUP BY Account#