簡體   English   中英

Pivot 表從 sql 到 linq

[英]Pivot table from sql to linq

我有以下兩個表EventsEventType

我需要做一些事情來顯示我的列 EventType 名稱(直接受益人、能力開發、Reach、Online Reach)和 Total 列,它是所有這些列的總和(特別是行):

結果

我的 sql 表是結構化的,就像在這張圖片上一樣: SQL 表

*注意:如果Events表中沒有eventTypeId,則pivot表中不顯示該列。

這些數字代表 1 月、2 月等舉行的所有活動的 TotalAttendants。

如果三月沒有累積事件,則該月應該是空的(三月也會在這里,但不是數字,只是空格)。

我嘗試遵循 linq 表達式:

var response = _context.Events
                    .Where(x => query.ProjectId.HasValue ? x.ProjectId.Equals(query.ProjectId) : true)
                    .Where(x => x.Date.Year.Equals(query.Year))
                    .Where(x => !x.IsDeleted)
                    .GroupBy(x => new { Year = x.Date.Year, Month = x.Date.Month })
                    .Select(x => new
                    {
                        DirectBeneficiaries = x.Where(m => m.EventTypeId == Domain.Enums.EventType.DirectBeneficiaries)
                            .Select(u => new EventTotal
                            {
                                Month = u.Date.Month.ToString("MMMM"),
                                FemaleAttendants = x.Sum(i => i.FemaleAttendants),
                                MaleAttendants = x.Sum(i => i.MaleAttendants),
                                TotalAttendants = x.Sum(i => i.TotalAttendants)
                            }),
                        CapacityDevelopment = x.Where(m => m.EventTypeId == Domain.Enums.EventType.CapacityDevelopment)
                            .Select(u => new EventTotal
                            {
                                Month = u.Date.Month.ToString("MMMM"),
                                FemaleAttendants = x.Sum(i => i.FemaleAttendants),
                                MaleAttendants = x.Sum(i => i.MaleAttendants),
                                TotalAttendants = x.Sum(i => i.TotalAttendants)
                            }),
                        Reach = x.Where(m => m.EventTypeId == Domain.Enums.EventType.Reach)
                            .Select(u => new EventTotal
                            {
                                Month = u.Date.Month.ToString("MMMM"),
                                FemaleAttendants = x.Sum(i => i.FemaleAttendants),
                                MaleAttendants = x.Sum(i => i.MaleAttendants),
                                TotalAttendants = x.Sum(i => i.TotalAttendants)
                            }),
                        OnlineReach = x.Where(m => m.EventTypeId == Domain.Enums.EventType.OnlineReach)
                            .Select(u => new EventTotal
                            {
                                Month = u.Date.Month.ToString("MMMM"),
                                FemaleAttendants = x.Sum(i => i.FemaleAttendants),
                                MaleAttendants = x.Sum(i => i.MaleAttendants),
                                TotalAttendants = x.Sum(i => i.TotalAttendants)
                            })
                    });

但我最后得到匿名類型,我不知道如何轉換到我的EventTotal model:

    public class EventTotal
    {
        public string Month { get; set; }
        public int? FemaleAttendants { get; set; }
        public int? MaleAttendants { get; set; }
        public int? TotalAttendants { get; set; }
    }

我的問題是:如何將其轉換為特定的 model?

更新#1:

我嘗試使用此代碼,但我有一個 db 異常。

"Column 'Events.TotalAttendants' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.\r\nThe multi-part identifier \"e.Date\" could not be bound.\r\nThe multi-part identifier \"e.Date\" could not be bound.\r\nThe multi-part identifier \"e.Date\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound.\r\nThe multi-part identifier \"e.EventTypeId\" could not be bound."

這是代碼

var eligibleEvents = _context.Events
        .Where(x => query.ProjectId.HasValue ? x.ProjectId.Equals(query.ProjectId) : true)
        .Where(x => x.Date.Year.Equals(query.Year))
        .Where(x => !x.IsDeleted)
        .GroupBy(x => new { Year = x.Date.Year, Month = x.Date.Month, EventType = (int)x.EventTypeId });

var eventTotals = eligibleEvents.GroupBy(x => new { Year = x.Key.Year, Month = x.Key.Month },

    (yearMonthCombination, eventsWithThisYearMonthCombination) => new EventTotal
    {
        Month = yearMonthCombination.Month,
        CapacityDevelopment = eventsWithThisYearMonthCombination.Where(u => u.Key.EventType == (int)Domain.Enums.EventType.CapacityDevelopment).Select(u => u.Sum(s => s.TotalAttendants)).Sum(),
        DirectBeneficiaries = eventsWithThisYearMonthCombination.Where(u => u.Key.EventType == (int)Domain.Enums.EventType.DirectBeneficiaries).Select(u => u.Sum(s => s.TotalAttendants)).Sum(),
        OnlineReach = eventsWithThisYearMonthCombination.Where(u => u.Key.EventType == (int)Domain.Enums.EventType.OnlineReach).Select(u => u.Sum(s => s.TotalAttendants)).Sum(),
        Reach = eventsWithThisYearMonthCombination.Where(u => u.Key.EventType == (int)Domain.Enums.EventType.Reach).Select(u => u.Sum(s => s.TotalAttendants)).Sum(),
        Total = eventsWithThisYearMonthCombination.Select(u => u.Sum(s => s.TotalAttendants)).Sum(),
        TotalAttendants = eventsWithThisYearMonthCombination.Select(u => u.Sum(s => s.TotalAttendants)).Sum()                        
    }).ToList();

return eventTotals;

因此,從您的Events序列中,您想要提取一系列EventTotals :每組來自相同 [Year, Month] 的 EventTotal。

  • 好吧,不是所有事件,只有那些沒有被刪除的事件
  • 而那些沒有被刪除的,你只想要那些與 ProjectId 和 Year 匹配的

首先:我們可以優化查詢的開始:將所有內容放在一個Where

var eligibleEvents = dbContext.Events
    .Where(event => !event.IsDeleted
        && event.Date.Year == query.Year)
        && (!query.ProjectId.HasValue || query.ProjectId == event.ProjectId)

換句話說:從所有事件中,只保留那些尚未刪除且Date.Year等於query.Year的事件。 根據query.ProjectId是否為 null,您保留所有這些事件,或者僅保留ProjectId的值等於query.ProjectId的那些事件

考慮將 OR 簡化如下:

(query.ProjectId == null) || (query.ProjectId == event.ProjectId)

現在從所有剩余的Events中,我們制作事件組。 具有相同 [年、月] 組合的所有事件將在一個組中。 從每個組中,我們只制作一個EventTotal

如果你使用 GroupBy,並且你想從每個 Group 中創建一個 object,就像我們一樣,考慮使用GroupBy 的重載,它有一個參數 resultSelector

繼續 LINQ:

var eventTotals = eligibleEvents.GroupBy(event => new
{
    Year = event.Date.Year,
    Month = event.Date.Month,
},

// parameter resultSelector: from every [Year, Month] combination,
// and all eligible events that have these values of Year / Month,
// make one new EventTotal:
(yearMonthCombination, eventsWithThisYearMonthCombination) => new EventTotal
{
    Month = yearMonthCombination.Month,

    // Count the zero or more FemaleAttendants:
    FemaleAttendants = eventsWithThisYearMonthCombination
        .Select(event => event.FemaleAttendants)
        .Sum(),

    // Count the zero or more MaleAttendants:
    MaleAttendants = eventsWithThisYearMonthCombination
        .Select(event => event.MaleAttendants)
        .Sum(),

    TotalAttendants = eventsWithThisYearMonthCombination
        .Select(event => event.TotalAttendants)
        .Sum(),
}

如果TotalAttendants始終是 FemaleAttendants 和 MaleAttendants 的總和,為什么它是一個單獨的列? 考慮更改屬性:

public int TotalAttendants => this.FemaleAttendants + this.MaleAttendants;

順便問一下,為什么你的隨從可以為空? 零服務員和null服務員有區別嗎? 如果沒有,請考慮刪除可為空的,只會讓您的生活更加困難。

如果你真的想要可以為空,那么零服務員什么時候應該轉換為 null? 唉,你忘了定義這個。

這不會填滿你的桌子

您特別要求EventTotals 我不明白這將如何幫助您填寫表格。

如果你想要一個帶有 [Month, DirectBenificaries, CapacityDevelopment, ...] 的行,我會使用 go 換一個不同的 resultSelector:

(yearMonthCombination, eventsWithThisYearMonthCombination) => new
{
    Month = yearMonthCombination.Month,

    DirectBenificiaries = eventsWithThisYearMonthCombination
        .Where(event => event.EventTypeId == dbContext.EventTypes
                        .Where(eventType => eventType.Name == "DirectBenificiaries")
        .Select(event => ...)
        .Sum(),

唉,您沒有告訴我們您使用什么屬性來構成 2020 年 1 月的 DirectBenificiaries。它是 DirectBenificiaries 類型的事件總數嗎? 或者是 2020 年 1 月 DirectBenificiaries 的服務員總數?

其他列類似。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM