首页 > 解决方案 > 按分组数据拆分列表

问题描述

我有一个我在数据表上显示的产品记录列表,这些记录按部门名称/ID 分组。从下图中,我返回的数据不包括突出显示的行。我正在尝试实现图像中显示的内容 - 对于已经按部门(沙漠、文具、家庭)分组的每组产品,获取总数和部门名称(以及我删除的其他列以减少混乱)附加到列表

在此处输入图像描述

我正在努力实现上述结果

这是我当前的代码/查询,它返回没有突出显示的行的数据

List<SaleDetailViewModel> list = new List<SaleDetailViewModel>();

NpgsqlCommand query = new NpgsqlCommand
     ("SELECT  q_department.q_name, q_saledetail.q_code, q_saledetail.q_description, " +
     "SUM(q_quantity) AS qtysum,  " + //running total of q_quantity for the product in that department     
     "FROM q_saledetail " +                    
     "LEFT JOIN q_department ON (q_saledetail.q_departmentid = q_department.q_code ) " +     
     "GROUP BY " +
     "q_saledetail.q_departmentid, q_department.q_name, q_saledetail.q_description, q_saledetail.q_code " +
     "ORDER BY q_saledetail.q_departmentid "
     , connectToDB);

NpgsqlDataReader read = query.ExecuteReader();

while(read.Read())
{
     var reportData = new SaleDetailViewModel();

     reportData.departmentName = read["q_name"].ToString(); //department name
     reportData.q_description = read["q_description"].ToString(); //product DESCRIPTION
     reportData.q_code = read["q_code"].ToString(); //product BAR CODE
     reportData.sumOfQuantity = Convert.ToDecimal(read["qtysum"]); //sum of quantity sold for that product


     list.Add(reportData);
}

connectToDB.Close();
return list;

我现在的挑战是为每组产品添加分组的部门行数据,并附加到将返回的列表中,即

//--
foreach(grouped dataset by department)
{
     //get the totals and heading for each set of data
     reportData.q_code = //insert department id
     reportData.q_description = //insert department name
     reportData.sumOfQuantity = // insert total for that department

     list.Add(reportData) //add that to the list that will be shown on view
}
//--

我可以使用 read.GetString() 获取分组数据的部门 ID 和代码。

string deptName = read.GetString(0);

如何继续循环遍历 dataReader 并为每个整体集合(如数量列)添加总计,并将其作为自己的一行添加到列表中?...从显示的图像中获取结果。

尝试更好地解释一下: 在我的 while 循环中,我如何聚合每个部门产品组的集合并创建一行以添加到列表中。或者有更好的方法来实现这一点..

标签: c#postgresqldatareader

解决方案


选项 1:Sql 和联合。

 SELECT  
    q_department.q_name,
    q_saledetail.q_code, 
    q_saledetail.q_description, 
     SUM(q_quantity) AS qtysum, --running total of q_quantity for the product in that department     
     FROM q_saledetail 
     LEFT JOIN q_department ON (q_saledetail.q_departmentid = q_department.q_code ) 
     GROUP BY 
     q_saledetail.q_departmentid, q_department.q_name, q_saledetail.q_description, q_saledetail.q_code


 UNION

 SELECT 
    q_department.q_name,
    '',
    '',
    sum(q_quantity)
    FROM q_saledetail 
     LEFT JOIN q_department ON (q_saledetail.q_departmentid = q_department.q_code ) 
    GROUP BY 
     q_saledetail.q_departmentid, q_department.q_name

     ORDER BY q_saledetail.q_departmentid 

通过删除一些标识与列表不同的字段,q_saledetail求和group by函数将对所有部门进行求和,而不是将总和分解。

抱歉,我不记得在手边的联合语句中排序是如何工作的,但我知道你只能在一个地方排序,要么是最后一条语句,要么是第一个,或者使用从联合中选择的外部查询。

您现在在数据中拥有的是每个部门的“总计”行,因为 q_code 或 q_description 字段为空白,您知道这些行是“总计”行。然后,您可以按部门排序数据集,然后按代码(asc 或 desc)排序,以便空代码字段位于该部门组的末尾并像这样显示。

选项 2:Linq 和一些手动代码工作

List<SaleDetailViewModel> list = new List<SaleDetailViewModel>();

while(read.Read())
{
    ... //Your mapping code
     list.Add(reportData);
}
var groupedList = list.GroupBy(x => x.departmentName);

这会给你一个IEnumerable<IGrouping<string, SaleDetailViewModel>.

什么是您的数据,现在按每个部门的名称分组,作为一个键您现在将循环groupedList并添加它的值IGrouping

foreach(var group in groupedList)
{
    var total = 0;
    foreach(var saledetail in group)
    {
        total += saledetail.sumOfQuantity;
    }


}

然后,您只需要添加逻辑以按这些组的顺序将其添加到列表/您的数据表中。

希望这可以帮助。


推荐阅读