如何在子组上使用 GroupBy

How to use GroupBy on a sub Group

也许我做错了,我是 Linq 的新手,但如果有人能帮助我,我将不胜感激。下面是我的代码。我正在尝试对 header 和详细信息 table 中的信息进行一些总结。所以我可以看到每个商家位置的总销售额和总访问次数(个人交易)。详情 table 会将 header table 中的 1 笔交易分成多行,因此 1 笔交易 ID 可以在详情 table.

中出现多次
            var query2 = db.sales_transaction_header
                           .Join(db.sales_transaction_detail,
                                 sth => sth.transaction_id,
                                 std => std.transaction_id,
                                 (sth, std) => new { TransHeader = sth, TransDetail = std })
                       .GroupBy(x => x.TransHeader.merchant_location_id)
                       .Select(g => new MerchantConsumerSalesDTO
                       {
                           TotalSales = g.Sum(x => x.TransDetail.transaction_amount),
                           MerchantId = g.FirstOrDefault().TransHeader.merchant_location_id,
                           TotalVisits = g.GroupBy(x => x.TransHeader.transaction_id).Select(g2 => g2.Count()),
                       })
                       .ToList();

TotalVisits 给我带来了各种各样的问题!我原来试过

TotalVisits = g.Select(x => x.TransHeader.transaction_id).Distinct().Count()

但这给了我莫名其妙的错误:

Unknown column 'Project3.merchant_location_id' in 'where clause'

如果没有 .Distinct(),它 returns Count() 是正确的,除了它是错误的数字!因为我只需要计算不同的值,但是使用 Distinct() 它会给我一个错误!所以我尝试在子组上使用 GroupBy。这甚至不允许我编译。我收到各种错误,例如 "cannot implicitly convert Ienumerable to int" 或 "Cannot convert anonymous type to int" - 我束手无策!我是完全走错了路还是这是一个很小很容易解决的问题??

提前致谢!

编辑: 也许这将有助于阐明我的意图。下面列出了我的 table 结构:

sales_transaction_header
    transaction_id
    merchant_location_id
    card
    transaction_date

sales_transaction_detail
    transaction_detail_id
    transaction_id
    transaction_amount
    seat_nbr

因此,基本上可以根据 seat_nbr 将单个交易分解为多个明细行。因此,如果我理解正确的话,第一个 groupby 应该只对商家 ID 进行分组,仍然为单个交易保留多行。我需要另一个组来计算唯一的交易 ID。正确吗?

此外,我生成的查询如下:

SELECT `Project2`.`merchant_location_id`, 
       `Project2`.`c1`, 
       `Project2`.`merchant_location_id1`, 
       (SELECT Count(1) AS `A1` 
        FROM   (SELECT DISTINCT `Extent7`.`transaction_id` 
                FROM   `sales_transaction_header` AS `Extent7` 
                       INNER JOIN `sales_transaction_detail` AS `Extent8` 
                               ON `Extent7`.`transaction_id` = 
                                  `Extent8`.`transaction_id` 
                WHERE  `Project2`.`merchant_location_id` = 
                       `Extent7`.`merchant_location_id`) AS 
               `Distinct2`) AS `C2` 
FROM   (SELECT `Apply1`.`merchant_location_id`, 
               `Apply1`.`merchant_location_id` 
                      AS `merchant_location_id1`, 
               (SELECT Sum(`Extent6`.`transaction_amount`) AS `A1` 
                FROM   `sales_transaction_header` AS `Extent5` 
                       INNER JOIN `sales_transaction_detail` AS `Extent6` 
                               ON `Extent5`.`transaction_id` = 
                                  `Extent6`.`transaction_id` 
                WHERE  `Apply1`.`merchant_location_id` = 
                       `Extent5`.`merchant_location_id`) AS 
               `C1` 
        FROM   (SELECT `Distinct1`.`merchant_location_id`, 
                       (SELECT `Extent3`.`transaction_id` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `transaction_id`, 
                       (SELECT `Extent3`.`merchant_location_id` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `MERCHANT_LOCATION_ID1`, 
                       (SELECT `Extent3`.`transaction_date` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `transaction_date`, 
                       (SELECT `Extent3`.`post_date` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `post_date`, 
                       (SELECT `Extent3`.`card_token` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `card_token`, 
                       (SELECT `Extent3`.`transaction_type` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `transaction_type`, 
                       (SELECT `Extent3`.`processed` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `processed`, 
                       (SELECT `Extent3`.`partner_transaction_id` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `partner_transaction_id`, 
                       (SELECT `Extent4`.`transaction_detail_id` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `transaction_detail_id`, 
                       (SELECT `Extent4`.`transaction_id` AS `TRANSACTION_ID1` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `TRANSACTION_ID1`, 
                       (SELECT `Extent4`.`transaction_amount` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `transaction_amount`, 
                       (SELECT `Extent4`.`charity_location_id` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `charity_location_id`, 
                       (SELECT `Extent4`.`event_type_id` 
                        FROM   `sales_transaction_header` AS `Extent3` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent4` 
                                       ON `Extent3`.`transaction_id` = 
                                          `Extent4`.`transaction_id` 
                        WHERE  `Distinct1`.`merchant_location_id` = 
                               `Extent3`.`merchant_location_id` 
                        LIMIT  1) AS `event_type_id` 
                FROM   (SELECT DISTINCT `Extent1`.`merchant_location_id` 
                        FROM   `sales_transaction_header` AS `Extent1` 
                               INNER JOIN `sales_transaction_detail` AS 
                                          `Extent2` 
                                       ON `Extent1`.`transaction_id` = 
                                          `Extent2`.`transaction_id`) AS 
                       `Distinct1`) AS `Apply1`) AS `Project2` 

更新:

最终,我选择了:

         var query = db.sales_transaction_header
                       .Join(db.sales_transaction_detail,
                             sth => sth.transaction_id,
                             std => std.transaction_id,
                             (sth, std) => new { TransHeader = sth, TransDetail = std })
                   .GroupBy(x => x.TransHeader.merchant_location_id)
                   .ToList()
                   .Select(g => new MerchantConsumerSalesDTO
                   {
                       TotalSales = g.Sum(x => x.TransDetail.transaction_amount),
                       MerchantId = g.Key,
                       TotalConsumerVisits = g.GroupBy(x => x.TransHeader.transaction_id).Count(),
                   });

这是由于我使用的 MySql 数据库的限制 - 它在 MSSQL 中工作得很好,显然不需要使用 ToList(),但至少它现在可以工作了!非常感谢,ROB!

chat 中进行讨论后,发现该行为是由于 MySql 连接器中的错误所致。

以下代码通过评估内存中的组来绕过此错误:

var query = db.sales_transaction_header
    .Join(db.sales_transaction_detail,
        sth => sth.transaction_id,
        std => std.transaction_id,
        (sth, std) => new {TransHeader = sth, TransDetail = std})
    .GroupBy(x => x.TransHeader.merchant_location_id)
    .ToList()
    .Select(g => new MerchantConsumerSalesDTO
    {
        TotalSales = g.Sum(x => x.TransDetail.transaction_amount),
        MerchantId = g.Key,
        TotalConsumerVisits = g.GroupBy(x => x.TransHeader.transaction_id).Count(),
    });

这是因为它生成了以下代码:

SELECT `GroupBy1`.`k1`      AS `merchant_location_id`, 
       `GroupBy1`.`a1`      AS `C1`, 
       (SELECT Count(1) AS `A1` 
        FROM   (SELECT DISTINCT `Extent3`.`transaction_id` 
                FROM   `sales_transaction_header` AS `Extent3` 
                       INNER JOIN `sales_transaction_detail` AS `Extent4` 
                               ON `Extent3`.`transaction_id` = 
                                  `Extent4`.`transaction_id` 
                WHERE  `GroupBy1`.`k1` = `Extent3`.`merchant_location_id`) AS 
               `Distinct1`) AS `C2` 
FROM   (SELECT `Extent1`.`merchant_location_id`    AS `K1`, 
               Sum(`Extent2`.`transaction_amount`) AS `A1` 
        FROM   `sales_transaction_header` AS `Extent1` 
               INNER JOIN `sales_transaction_detail` AS `Extent2` 
                       ON `Extent1`.`transaction_id` = 
                          `Extent2`.`transaction_id` 
        GROUP  BY `Extent1`.`merchant_location_id`) AS `GroupBy1` 

在MySql中,内部selects不能引用外部结果,所以这一行:

`GroupBy1`.`k1` = `Extent3`.`merchant_location_id`

失败,因为 GroupBy1 超出了 select 的范围。

修复方法是在组后添加 ToList(),以便最终的 select(和求和)在内存中完成