我在获取linq到SQL查询时遇到了麻烦,并且想知道是否有人可以提供帮助。我有这些表:'订单','订单产品','产品'和'用户'。我希望得到每个'用户'订购的产品数量(包含在ProductID产品'中的ProductID产品)数量的详细信息。用户的UserID包含在“订单”表中,“OrderProducts”orderID与“订单”中的orderID相关。最终结果应该是这样的:
User1 User2 User3 Product1 100 75 17 Product2 24 78 18 Product3 82 48 35
因此,它按UserID和ProductID分组,并使用该userID获取所有分组ProductID的数量之和。我希望这是有道理的。非常感谢任何帮助,谢谢!
这是一个简化的数据库细分:
产品
- 产品ID
- 产品名称
订单
- 订单ID
- 用户ID
订购产品
- 订单ID
- 产品ID
- ProductQty
用户
- 用户ID
- 用户名
答案 0 :(得分:2)
这是一个查询,它会为您提供Users
,Products
和Count
的列表:
from op in OrderProducts
group op by new {op.Order.User, op.Product} into g
select new
{
g.Key.User.UserName,
g.Key.Product.ProductName,
Count=g.Sum(op => op.ProductQty)
}
它不会以您想要的确切格式提供结果,但它只会让您使用Linq。
另请注意,这不会提取任何额外数据 - (Users
或Products
计数为0)。这可能是也可能不是你想要的。
[编辑] 这是另一个查看(实际上是两个)的查询:
from p in Products
from u in Users
let i = (from op in OrderProducts
where op.Order.User == u && op.Product == p
select op.ProductQty)
let quant = i.Count() == 0 ? 0 : i.Sum(v=>v)
select new {p.ProductName, u.UserName, Quantity = quant}
//group new {u.UserName, Quantity = quant} by p into g
//select new {g.Key.ProductName, Users = g.AsEnumerable()}
原样,这应该给你直接的结果(ProductName,UserName,Quantity表)。注释掉的部分将按产品分组,这取决于您呈现结果的方式,可能就是您想要的。
答案 1 :(得分:0)
如果您在数据库中设置了适当的关系(因此,在DBML中),您可能需要考虑这样的事情(UNTESTED):
<table>
<tr>
<asp:Repeater ID="_users" runat="server">
<ItemTemplate>
<td><%# Eval("UserName") %></td>
</ItemTemplate>
</asp:Repeater>
</tr>
<asp:Repeater ID="_products" runat="server">
<ItemTemplate>
<tr>
<td><%# Eval("Product.ProductName") %></td>
<asp:Repeater ID="_users" runat="server" DataSource='<%# GetUsersProducts(Eval("ProductID")) %>'>
<ItemTemplate>
<td><%# Eval("count") %></td>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
</table>
代码隐藏:
protected void Page_Load(object sender, EventArgs e)
{
_users.DataSource = context.Users.OrderBy(u => u.UserName);
_users.DataBind();
_products.DataSource = context.Products;
_products.DataBind();
}
protected object GetUsersProducts(string ProductID)
{
var prodord = from op in context.OrderProducts where op.ProductID == ProductID select op;
return from u in context.Users.OrderBy(u2 => u2.UserName) select new {
count = prodord.Where(op => op.Order.User.UserID == u.UserID).Sum(op => op.ProductQty)
};
}
你显然想要改变你的标记和一些对象类型,但我希望这会让你前进。我尝试尽可能多地使用自动生成的类对象结构,以避免创建不可读的LINQ查询。
答案 2 :(得分:0)
您要求的结果形状称为 pivot 。它具有数据驱动的列,而不是在查询运行之前声明的列。
这里的技巧是将结果投影到一个类型,其中“属性”可以在运行时变化。我做了类似here
的事情这是针对您的特定问题:
// grab relationally-shaped results from database
var queryResult =
(
from u in myDataContext.Users
from o in u.Orders
from op in o.OrderProducts
select new
{
UserName = u.UserName,
ProductName = op.ProductName,
Quantity = op.Quantity
}
).ToList()
// now use a LinqToObjects query to pivot
List<XElement> pivotedResults =
(
from x in queryResult
group by x.ProductName into g
select new XElement(g.Key,
from y in g
group by y.UserName into subg
select new XAttribute(subg.Key, subg.Sum(z => z.Quantity))
).ToList();