Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Most popular" GROUP BY in LINQ?

Assuming a table of tags like the stackoverflow question tags:

TagID (bigint), QuestionID (bigint), Tag (varchar)

What is the most efficient way to get the 25 most used tags using LINQ? In SQL, a simple GROUP BY will do:

SELECT Tag, COUNT(Tag) FROM Tags GROUP BY Tag

I've written some LINQ that works:

var groups = from t in DataContext.Tags
             group t by t.Tag into g
             select new { Tag = g.Key, Frequency = g.Count() };
return groups.OrderByDescending(g => g.Frequency).Take(25);

Like, really? Isn't this mega-verbose? The sad thing is that I'm doing this to save a massive number of queries, as my Tag objects already contain a Frequency property that would otherwise need to check back with the database for every Tag if I actually used the property.

So I then parse these anonymous types back into Tag objects:

groups.OrderByDescending(g => g.Frequency).Take(25).ToList().ForEach(t => tags.Add(new Tag()
{
    Tag = t.Tag,
    Frequency = t.Frequency
}));

I'm a LINQ newbie, and this doesn't seem right. Please show me how it's really done.

like image 832
tags2k Avatar asked Oct 30 '08 16:10

tags2k


3 Answers

If you want Tag objects, why not create them directly from your Linq query?

var groups = from t in DataContext.Tags
             group t by t.Tag into g
             select new Tag() { Tag = g.Key, Frequency = g.Count() };

return groups.OrderByDescending(g => g.Frequency).Take(25);
like image 101
GalacticCowboy Avatar answered Nov 05 '22 17:11

GalacticCowboy


If you use the verbose form of the syntax, your code will be verbose. Here's an alternative:

List<Tag> result = 
  db.Tags
  .GroupBy(t => t.Tag)
  .Select(g => new {Tag = g.Key, Frequency = g.Count()})
  .OrderByDescending(t => t.Frequency)
  .Take(25)
  .ToList()
  .Select(t => new Tag(){Tag = t.Tag, Frequency = t.Frequency})
  .ToList();
like image 42
Amy B Avatar answered Nov 05 '22 15:11

Amy B


I'm pretty sure you've got it right. And, the SQL that LINQ generates and will send to your db will look just like the SQL you started with, so while you're doing a bit more typing, your database isn't doing any more work.

like image 32
James Curran Avatar answered Nov 05 '22 15:11

James Curran