8

我想将以下查询转换为 LINQ 语法。我在设法让它工作时遇到了很多麻烦。我实际上尝试从 LINQ 开始,但发现如果我反过来写它可能会更好。

SELECT
    pmt.guid,
    pmt.sku,
    pmt.name,
    opt.color,
    opt.size,
    SUM(opt.qty) AS qtySold,
    SUM(opt.qty * opt.itemprice) AS totalSales,
    COUNT(omt.guid) AS betweenOrders
FROM
    products_mainTable pmt 
        LEFT OUTER JOIN 
            orders_productsTable opt ON opt.products_mainTableGUID = pmt.guid
            LEFT OUTER JOIN orders_mainTable omt ON omt.guid = opt.orders_mainTableGUID AND
                (omt.flags & 1) = 1
GROUP BY
    pmt.sku, opt.color, opt.size, pmt.guid, pmt.name
ORDER BY
    pmt.sku

最终结果是一个表格,向我显示了有关产品的信息,如您在上面看到的。如何使用理解语法以 LINQ 形式编写此查询?

此外,我可能想要添加额外的过滤器(例如,添加到 orders_mainTable)。

这是我尝试制作的一个示例,并且相当接近,但不确定它是否是“正确”的方式,并且无法从 orders_productsTable 中按大小和颜色对其进行分组。

from pmt in products_mainTable
let Purchases = 
        from opt in pmt.orders_productsTable
        where ((opt.orders_mainTable.flags & 1) == 1)
        where ((opt.orders_mainTable.date_completedon > Convert.ToDateTime("01/01/2009 00:00:00")))
        select opt
orderby pmt.sku
select new {
    pmt.guid,
    pmt.sku,
    pmt.name,
    pmt.price,  
    AvgPerOrder = Purchases.Average(p => p.qty).GetValueOrDefault(0),
    QtySold = Purchases.Sum(p => p.qty).GetValueOrDefault(),
    SoldFor = Purchases.Sum(p => p.itemprice * p.qty).GetValueOrDefault()           
}

*编辑:

为了更明确一点,这样你就可以理解我想要做什么,这里有一些更多的解释。

商品存放在 products_mainTable 订单存放在 orders_mainTable 已下单的商品存放在 orders_productsTable

我想根据产品、订单等创建几个报告。钻取数据并找到有意义的位以显示给最终用户。

在这种情况下,我试图显示在一段时间内购买了哪些产品,并且是最受欢迎的。卖出了多少,价格是多少,每个订单的突破是多少。也许不是最好的顺序,但我只是在试验并选择了这个。

所有表都与其他表有关系。所以从产品表中,我可以得到订购该产品的订单等。

我遇到的最大问题是了解 LINQ 的工作原理,尤其是在分组、聚合数据、扩展、子查询等方面。这很有趣,但它开始变得令人沮丧,因为我很难找到有关如何执行此操作的详细解释。

4

3 回答 3

5

我也是 LINQ 的初学者。我不知道这是否是按多个字段分组的正确方法,但我认为您必须将这些分组字段转换为表示键。因此,假设您的所有分组字段都是字符串或整数,您可以按如下方式创建一个键:

        var qry = from pmt in products_mainTable
                  join opt in orders_productsTable on pmt.guid equals opt.products_mainTableGUID
                  join omt in orders_mainTable on opt.orders_mainTableGUID equals omt.guid
                  where (opt.orders_mainTable.flags & 1) == 1
                  group omt by pmt.sku + opt.price + opt.size + pmt.guid + pmt.name into g
                  orderby g.sku
                  select new
                  {
                      g.FirstOrDefault().guid,
                      g.FirstOrDefault().sku,
                      g.FirstOrDefault().name,
                      g.FirstOrDefault().color,
                      g.FirstOrDefault().price,
                      AvgPerOrder = g.Average(p => p.qty).GetValueOrDefault(0),
                      QtySold = g.Sum(p => p.qty).GetValueOrDefault(),
                      SoldFor = g.Sum(p => p.itemprice * p.qty).GetValueOrDefault()
                  };

我没有对此进行测试,所以请看看这是否对您有任何帮助。

于 2009-02-04T21:44:59.773 回答
3

布鲁诺,非常感谢您的帮助!FirstOrDefault() 可能是最大的帮助。遵循您所做的一些事情,以及另一个资源,我想出了以下似乎效果很好的资源!下面的这个 LINQ 查询几乎完全复制了我上面发布的 SQL。

这是我在 LINQ 中执行 LEFT OUTER JOIN 时发现的另一个资源:博客文章

最终答案:

 from pmt in products_mainTable
    join opt in orders_productsTable on pmt.guid equals opt.products_mainTableGUID into tempProducts
    from orderedProducts in tempProducts.DefaultIfEmpty()
    join omt in orders_mainTable on orderedProducts.orders_mainTableGUID equals omt.guid into tempOrders
    from ordersMain in tempOrders.DefaultIfEmpty()
    group pmt by new { pmt.sku, orderedProducts.color, orderedProducts.size } into g
    orderby g.FirstOrDefault().sku
    select new {
        g.FirstOrDefault().guid,
        g.Key.sku,
        g.Key.size, 
        QTY = g.FirstOrDefault().orders_productsTable.Sum(c => c.qty),
        SUM = g.FirstOrDefault().orders_productsTable.Sum(c => c.itemprice * c.qty),
        AVG = g.FirstOrDefault().orders_productsTable.Average(c => c.itemprice * c.qty),
        Some = g.FirstOrDefault().orders_productsTable.Average(p => p.qty).GetValueOrDefault(0),
    }
于 2009-02-05T04:32:25.223 回答
0

这对我很有帮助,谢谢。我有一个类似的问题,我试图解决只是我的案例要简单得多,因为我没有任何连接。我只是想对一个字段进行分组,得到另一个字段的最小值,然后计数。(同一查询中的最小值和计数)

这是我想用 Linq 语法重新创建的 SQL:

select t.Field1, min(t.Field2), COUNT(*)
from SomeTable t
group by t.Field1
order by t.Field1

感谢您的帖子,我最终设法想出了这个:

from t in SomeTable
group t by new { t.Field1 } into g
orderby g.Key.Field1
select new
{ 
  g.Key.Field1,
  code = g.Min(c => c.Field2),
  qty = g.Count()
}

这在幕后创建了以下 SQL:

SELECT [t1].[Field1], [t1].[value] AS [code], [t1].[value2] AS [qty]
FROM (
    SELECT MIN([t0].[Field2]) AS [value], COUNT(*) AS [value2], [t0].[Field1]
    FROM [SomeTable] AS [t0]
    GROUP BY [t0].[Field1]
    ) AS [t1]
ORDER BY [t1].[Field1]

完美,正是我想要做的。对我来说,关键是您展示了在新的 {} 中执行此操作的可能性,这是我从未考虑过尝试的事情。这是巨大的,我现在觉得我对未来有了更好的理解。

于 2009-05-01T15:37:35.990 回答