如何使用 LINQ 从一个表中获取所有列并从另一个表中获取少数列?

问题描述 投票:0回答:5
SELECT 
    p.Id, p.Item, h.Date,h.Shop,
    SUM(h.Harvested) AS Harvested 
FROM 
    Plantings p 
LEFT JOIN 
    Harvests h ON p.Id = h.Id
GROUP By p.Id, p.Item, h.Date, h.Shop

此代码用于从

Plantings
表中选择所有列,并从
Harvests
表中选择几列(即收获和日期的总和)。

我的要求是使用LINQ方法重写这段代码。

Plantings
桌子

身份证 项目 已种植
3 胡萝卜 2.00
4 苹果 1.00

Harvests
桌子

HId 项目 收获 身份证 日期 商店
1 胡萝卜 10.00 3 2024 年 4 月 9 日 4
2 苹果 20.00 4 2024 年 9 月 9 日 11
3 胡萝卜 5.00 3 2024 年 4 月 9 日 4
4 胡萝卜 3 2024 年 7 月 9 日 2

这是我尝试过的

IEnumerable DataSource = (from p in _context.Plantings 
                          join h in _context.Harvests on p.Id equals h.Id 
                          select t1).ToList();

预期产出表

身份证 项目 收获
3 胡萝卜 15.00
4 苹果 20.00
3 胡萝卜
linq asp.net-core
5个回答
3
投票

您可以在 LINQ 中创建一个带有子查询的对象。

var data = (
    from p in _context.Plantings 
    select new {
        p,
        Harvested = _context.Harvests.Where(h => h.Id == p.Id).Sum(h => h.Harvested),
    }
).ToList();

通常你会有某种外键关系,那么你就可以这样做

var data = (
    from p in _context.Plantings 
    select new {
        p,
        Harvested = p.Harvests.Sum(h => h.Harvested),
    }
).ToList();

0
投票

因为您的种植表和收获表是基于 Id 的

one-to-many
映射。所以你需要
join...into
为此。

类定义:

    public class Planting
    {
        public int Id { get; set; }
        public string Item { get; set; }
        public double Planted { get; set; }
    }

    public class Harvest
    {
        public int HId { get; set; }
        public string Item { get; set; }
        public double Harvested { get; set; }
        public int Id { get; set; }
    }

Linq 连接:

    var Plantings = new List<Planting>
    {
        new Planting {Id = 3, Item = "Carrot", Planted = 2.0},
        new Planting {Id = 4, Item = "Apple", Planted = 1.0}
    };
    var Harvests = new List<Harvest>
    {
        new Harvest {HId = 1, Item = "Carrot", Harvested = 10.0, Id = 3},
        new Harvest {HId = 2, Item = "Apple", Harvested = 20.0, Id = 4},
        new Harvest {HId = 3, Item = "Carror", Harvested = 5.0, Id = 3}
    };

    // assuming Id in Plantings are distinct
    var joined = (from planting in Plantings
        join harvest in Harvests on planting.Id equals harvest.Id into harvestsForPlanting
        select new
        {
            Id = planting.Id,
            Item = planting.Item,
            Harvested = harvestsForPlanting.Sum(h => h.Harvested)
        }).ToList();

结果: enter image description here


0
投票
var result = _context.Plantings
.GroupJoin(
    _context.Harvests,
    planting => planting.Id,
    harvest => harvest.Id,
    (planting, harvests) => new
    {
        planting.Id,
        planting.Item,
        Harvested = harvests.Sum(h => (decimal?)h.Harvested) ?? 0
    }
).ToList();

说明:

  1. GroupJoin
    方法:用于允许
    _context.Plantings
    _context.Harvests
  2. 之间进行左连接
  3. Sum(h => (decimal?)h.Harvested) ?? 0
    :基于左连接会有null值,所以将null的求和转换为0

0
投票

所以你有两张桌子,

Plantings
Harvests
。这两个表之间存在一对多关系。每个
Planting
都有零个或多个
Harvests
,每个
Harvest
恰好是一个
Planting
的收获,即外键
Harvest.Id
所指的PLANTING。

您将拥有与以下类似的课程。 (提示:下次您提出问题时请考虑给我们这些课程)。

class Planting
{
    public int Id {get; set;}            // primary key
    public string Item {get; set;}       // what crop has been planted on this Planting
    public decimal Planted {get; set;}   // the amount of planted crops
}

class Harvest
{
    public int Hid {get; set;}           // primary key
    public string Item {get; set;}       // what crop has been Harvested?
    public decimal Harvested {get; set;} // the amount of harvested crops

    // This Harvest was done on exactly one Planing, nameley the Planting
    // that the foreign key refers to:
    public int Id {get; set;}            // foreign key to Planting
}

还有你的 DbContext:

class MyDbContext : DbContext
{
    public DbSet<Planting> Plantings {get; set;}
    public DbSet<Harvest> Harvests {get; set;}
}

顺便问一下,您是否注意到您的数据库没有第一范式?使用此表格布局,您可以在仅包含胡萝卜的种植园中收获苹果。或者这是您想要考虑的场景吗?

建议:您的外键有一个令人困惑的标识符。考虑将名称 Id 更改为 PlantingId。仅为主键保留名称 Id。这将帮助代码的读者理解这些属性的含义。

要求:给我所有种植园的

Id
Item
,每个种植园收获的物品总数

...即使您在只有胡萝卜的种植园中收获了苹果。但是,嘿,这就是 SQL 命令的作用。

每当您有一对多关系,并且需要从相关子项中获取“具有某些值的项的属性”时,请考虑使用 Queryable.GroupJoin 的重载之一。如果您需要获取“项目的属性,每个项目都有它们所属项目的一些属性”,请考虑使用 Queryable.Join.

的重载之一

由于您想要“种植及其相关子项收获的一些信息”,我们需要使用 GroupJoin。我几乎总是使用带有参数

resultSelector
的重载。这使我们能够准确地指定我们想要的内容。

// GroupJoin Plantings with Harvests:
var plantingsWithTotalHarvested = dbContext.Plantings.GroupJoin(
    dbContext.Harvests,
    planting => planting.Id,      // from every Planting take the primary key
    harvest => harvest.Id,        // from every Harvest take the foreign key to
                                  // the Planting it belongs to.

    // parameter resultSelector: take every planting,
    // each with its zero or more Harvest to create one new
    (planting, harvestsOfThisPlanting) => new
    {
        Id = planting.Id,
        Item = planting.Item,

        Harvested = harvestsOfThisPlanting.Select(harvest => harvest.Harvested)
                                          .Sum(),
    });

用文字来说:拿种植和收获表格。从表中的每个种植中查找属于该种植的所有收获。从每个种植中,获取属性

Id
Item
的值。从属于该种植的每个收获中获取属性
Harvested
的值并将其相加。将结果放入属性
Harvested


-1
投票

以下内容将帮助您实现您想要的目标:

var finalResult = (from h in  _context.Harvests         
    join p in  _context.Plantings on h.Id equals p.Id
    group h by new { p.Id, p.Item } into g
    select new
    {
        Id = g.Key.Id,
        Item = g.Key.Item,
        Harvested = g.Sum(m => m.Harvested)
    }).ToList();

相当于

var finalResult =  _context.Harvests.Join( _context.Plantings, h => h.Id, p => p.Id, (h, p) => (h,p))
                        .GroupBy(g => new { g.h.Id, g.h.Item }).Select(f => new
                        {
                            Id = f.Key.Id, Item = f.Key.Item, Harvested = f.Sum(d => d.h.Harvested)
                        });
© www.soinside.com 2019 - 2024. All rights reserved.