C# 如何在Linq查询中找到产品编号x订购最多的城市?
我的班级结构如下C# 如何在Linq查询中找到产品编号x订购最多的城市?,c#,sql,linq,C#,Sql,Linq,我的班级结构如下 public class Users { public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } public int CityId { get; set; } } public class Order { public int Id { get; set; } public int UserI
public class Users
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int CityId { get; set; }
}
public class Order
{
public int Id { get; set; }
public int UserId { get; set; }
}
public class OrderDetail
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public int Amount { get; set; }
}
select * from
(select u.CityId, sum(od.Amount),
ROW_NUMBER() over(order by sum(od.Amount) desc) as rn
from Order o
inner join OrderDetail od on o.Id = od.OrderId
inner join Users u on u.Id = o.UserId
where od.ProductId = x
group by u.CityId
)
where rn = 1;
我想作为Linq编写的查询如下:
public class Users
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int CityId { get; set; }
}
public class Order
{
public int Id { get; set; }
public int UserId { get; set; }
}
public class OrderDetail
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public int Amount { get; set; }
}
select * from
(select u.CityId, sum(od.Amount),
ROW_NUMBER() over(order by sum(od.Amount) desc) as rn
from Order o
inner join OrderDetail od on o.Id = od.OrderId
inner join Users u on u.Id = o.UserId
where od.ProductId = x
group by u.CityId
)
where rn = 1;
我试过很多东西,但都不符合结构。现在感谢您。请尝试以下内容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Context db = new Context();
int productId = 123;
var results = (from u in db.Users
join o in db.Order on u.Id equals o.UserId
join od in db.OrderDetails.Where(x => x.ProductId == productId) on o.Id equals od.OrderId
select new { u = u, o = o, od = od }
).GroupBy(x => x.u.CityId)
.Select(x => new { city = x.Key, sum = x.Sum(y => y.od.Amount) })
.OrderByDescending(x => x.sum)
.ToList();
}
}
public class Context
{
public List<Users> Users { get;set;}
public List<Order> Order { get; set; }
public List<OrderDetail> OrderDetails { get; set; }
}
public class Users
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public int CityId { get; set; }
}
public class Order
{
public int Id { get; set; }
public int UserId { get; set; }
}
public class OrderDetail
{
public int Id { get; set; }
public int OrderId { get; set; }
public int ProductId { get; set; }
public int Amount { get; set; }
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
Context db=newcontext();
int productId=123;
var results=(从u到db.Users)
在数据库中加入o。u.Id上的顺序等于o.UserId
在db.OrderDetails中加入od,其中o.Id上的(x=>x.ProductId==ProductId)等于od.OrderId
选择新的{u=u,o=o,od=od}
).GroupBy(x=>x.u.CityId)
.Select(x=>new{city=x.Key,sum=x.sum(y=>y.od.Amount)})
.OrderByDescending(x=>x.sum)
.ToList();
}
}
公共类上下文
{
公共列表用户{get;set;}
公共列表顺序{get;set;}
公共列表OrderDetails{get;set;}
}
公共类用户
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串姓氏{get;set;}
public int CityId{get;set;}
}
公共阶级秩序
{
公共int Id{get;set;}
public int UserId{get;set;}
}
公共类OrderDetail
{
公共int Id{get;set;}
公共int-OrderId{get;set;}
public int ProductId{get;set;}
公共整数金额{get;set;}
}
}
显然,您有一个表Cities
与用户具有一对多关系:每个城市都有零个或多个用户,每个用户只居住在一个城市,即外键用户.CityId
所指的城市
类似地,在用户
和订单
之间存在一对多关系:每个用户下了零个或多个订单,每个订单都是由一个用户下的,即外键Order.UserId
所指的用户
另外两种一对多关系:订单
和订单详细信息
和产品
和订单详细信息
:每个产品都是零个或多个订单数据项下的产品。每个OrderDetail都只涉及一个产品,即外键ProductId所指的产品
如何在Linq查询中找到产品编号x订购最多的城市
您对用户、订单、订单详细信息不感兴趣,甚至对所有产品都不感兴趣,只对产品X感兴趣。您想要的是该产品X订购最多的城市
为此,您需要内部联接Cities-Users-Orders-OrderDetails,并只保留[City;OrderDetail.Amount;Product.Id]的组合
删除所有与“产品编号X”无关的组合。其余的组合都是关于Product X.GroupBy City的,并将该城市的所有OrderDetails的所有金额相加
按总和降序排列,保留第一个
我的天,这将是一个大林肯!幸运的是,这并不难
首先,我们进行内部联接以生成组合[City、User、Order、OrderDetails],并且只保留所需的属性:[City、Amount、ProductId]
var productNumberX = ...;
var result = dbContext.Cities.Join(dbContext.Users, // inner join Cities and Users
city => city.Id, // from every city take the primary key
user => user.CityId, // from every user take the foreign key
(city, user) => new // when they match, make one new
{
City = city,
UserId = user.Id, // for the next join we only need the UserId
})
通过第二次连接继续LINQ:通过订单连接:
.Join(dbContext.Orders,
previousJoinResult => previousJoinResult.UserId, // from previous join take the UserId
order => order.UserId, // from the Order take the UserId
(previousJoinResult, order) => new // when they match, make one new
{
City = previousJoinResult.City,
OrderId = order.Id, // for the next Join we only need the OrderId
})
第三次加入:加入OrderDetails。记住amount和ProductId
.Join(dbContext.OrderDetails,
previousJoinResult => previousJoinResult.OrderId, // get the OrderId from previous join
orderDetail => orderDetail.OrderId, // get foreign key OrderId
(previousJoinResult, orderDetail) => new
{
City = previousJoinResult.City,
Amount = orderDetail.Amount,
ProductId = orderDetail.ProductId,
})
仅保留关于“产品编号X”的[City、Amount、ProductId]组合:
现在我们有了所有productNumberX的组合[City,Amount,ProductId]。
把同一个城市分成几组。使用
所以:
关键选民:同一城市的群体
ElementSelector:仅显示所有joinresult组合的数量
结果选择器:每个城市及其金额之和
我们不需要ProductId,它们都是一样的
.GroupBy(joinResult => joinResult.City,
// elementSelector: keep only the Amount of the JoinResult
joinResult => joinResult.Amount,
// parameter resultSelector: for every City, and all Amounts of orderDetails of Orders
// that were placed by Users in this City, make one new
// containing the City and the sum of the amounts
(city, amountsInThisCity) => new
{
City = city,
TotalAmount = amountsInThisCity.Sum(),
})
因此,对于每个城市,至少有一个用户下了一个订单,订单上有关于产品X的OrderDetail,您现在有了该城市所有用户的所有订单中产品X的所有OrderDetails的金额之和
按TotalAmount降序排序,并取第一个:
.OrderByDescending(city => city.TotalAmount)
.FirstOrDefault();
结果:
产品编号x订购最多的城市,如果没有人订购过产品编号x,则为空
注意,他们的查询具有其中rn=1
,因此他们只获取金额最高的订单。您是否使用实体框架?是否具有类似用户.订单
的导航属性?如果没有,创建它们。