简体   繁体   中英

Aggregate data from two tables using single linq query

I am quite new to LINQ and not aware of its full features yet.

I have two tables like below

Links
----------------------
LinkId 
LinkTitle 
DateAdded


Articles
----------------------
ArticleId
ArticleTitle
DateAdded

I am trying to create resultset using a single linq query that will output the data like below

Year
Month
NoOfLinksAdded
NoOfArticleAdded

Any help would be highly appreciated.

Update: Thats what I did so far

var grouped = from p in Links 
              group p by new { month = p.DateAdded.Month,year= p.DateAdded.Year } into d 
              select new { Month = d.Key.month, Year= d.Key.year, NoOfLinksAdded = d.Count() };

Here's how to do it in a single query, but it's not very pretty...

var query = from n in Enumerable.Range(0, 1) //we need something to start our query from
            //shape the articles so we can append them to the links 
            let articlesShaped = from a in articles
                                 select new
                                 {
                                     IsLink = false,
                                     IsArticle = true,
                                     a.DateAdded,
                                 }
            //shape the links so we can append them to the articles
            let linksShaped = from l in links
                              select new
                              {
                                  IsLink = true,
                                  IsArticle = false,
                                  l.DateAdded,
                              }
            //append the links and articles together
            let articlesAndLinks = articlesShaped.Concat(linksShaped)
            from a in articlesAndLinks
            group a by new { a.DateAdded.Month, a.DateAdded.Year } into grouping
            select new
            {
                grouping.Key.Year,
                grouping.Key.Month,
                NoOfLinksAdded = grouping.Where(a1 => a1.IsLink).Count(),
                NoOfArticleAdded = grouping.Where(a1 => a1.IsArticle).Count(),
            };

and here are the results:

这是输出

It'd be more maintainable if you split it into individual steps. It wouldn't cost you any performance either, because the execution only happens once you iterate over the result set due to the deferred execution.

If we split the code up into steps it becomes the following (which is much nicer in my opinion)

//shape the articles so we can append them to the links                   
var articlesShaped = from a in articles
                     select new
                     {
                         IsLink = false,
                         IsArticle = true,
                         a.DateAdded,
                     };

//shape the links so we can append them to the articles
var linksShaped = from l in links
                  select new
                  {
                      IsLink = true,
                      IsArticle = false,
                      l.DateAdded,
                  };

//append the links and articles together
var articlesAndLinks = articlesShaped.Concat(linksShaped);

var query = from a in articlesAndLinks
            //group by the month and year
            group a by new { a.DateAdded.Month, a.DateAdded.Year } into grouping
            select new
            {
                grouping.Key.Year,
                grouping.Key.Month,
                //get the number of links
                NoOfLinksAdded = grouping.Where(a1 => a1.IsLink).Count(),
                //get the number of articles
                NoOfArticleAdded = grouping.Where(a1 => a1.IsArticle).Count(),
            };

Finally, here's a full version that you can run so you can see the code in action:

//make some test data
var links = new []
{
    new    
    {
        LinkId = 1,
        LinkTitle = "A link",
        DateAdded = new DateTime(2012, 5, 1),
    },
    new
    {
        LinkId = 2,
        LinkTitle = "Another link",
        DateAdded = new DateTime(2012, 5, 1),
    },
    new
    {
        LinkId = 3,
        LinkTitle = "A link bro!",
        DateAdded = new DateTime(2012, 6, 1),
    },
    new
    {
        LinkId = 4,
        LinkTitle = "A link dude",
        DateAdded = new DateTime(2012, 6, 1),
    },
    new
    {
        LinkId = 5,
        LinkTitle = "A link man!",
        DateAdded = new DateTime(2012, 7, 1),
    },
};
//make some test data
var articles = new []
{
    new
    {
        ArticleId = 1,
        ArticleTitle = "An article",
        DateAdded = new DateTime(2012, 6, 1),
    },
    new
    {
        ArticleId = 2,
        ArticleTitle = "An article",
        DateAdded = new DateTime(2012, 6, 1),
    },
    new
    {
        ArticleId = 3,
        ArticleTitle = "An article",
        DateAdded = new DateTime(2012, 7, 1),
    },
    new
    {
        ArticleId = 4,
        ArticleTitle = "An article",
        DateAdded = new DateTime(2012, 8, 1),
    },
};

//shape the articles so we can append them to the links                   
var articlesShaped = from a in articles
                     select new
                     {
                         IsLink = false,
                         IsArticle = true,
                         a.DateAdded,
                     };
//shape the links so we can append them to the articles
var linksShaped = from l in links
                  select new
                  {
                      IsLink = true,
                      IsArticle = false,
                      l.DateAdded,
                  };
//append the links and articles together
var articlesAndLinks = articlesShaped.Concat(linksShaped);

var query = from a in articlesAndLinks
            //group by the month and year
            group a by new { a.DateAdded.Month, a.DateAdded.Year } into grouping
            select new
            {
                grouping.Key.Year,
                grouping.Key.Month,
                //get the number of links
                NoOfLinksAdded = grouping.Where(a1 => a1.IsLink).Count(),
                //get the number of articles
                NoOfArticleAdded = grouping.Where(a1 => a1.IsArticle).Count(),
            };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM