Linq counting second grouping and counting without grouping

别来无恙 提交于 2021-01-29 13:55:45

问题


I'm trying to build a summary query that i will be using for statistics.

i have a dataTable with the folowing columns (approx 18000 rows) :

Artist / Album / file_path (one for each song) / rating / 

each artist has 1 or several album with has songs and each songs have a rating

I want to have the following result :

For each artist ID (more reliable than the artist name), the total number of albums, the total number of songs, and the total number of ratings equal to 5.

Artist x / #album / #songs / #rating = 5 / song.first() //in song.first i have access to the file path, it can be any file path from the artist hence the first one.

I've been pulling my hair for several hours now and i cannot manage to get the # of albums per artist :( This is what i've been trying so far :

i have a Class for the query :

  public class art_detail
    {
        public string artiste { get; set; }
        public string fp { get; set; } // the file_path
        public int nbr_album { get; set; }
        public int nbr_song { get; set; }
        public int nbr_rat5 { get; set; }
    }

this is the query i came up to :

            var result = from res in Globals.ds.Tables[0].AsEnumerable() // the table
           .GroupBy(x =>  new { art = x.Field<int>("Artist_ID"), alb = x.Field<string>("album") })
           .Select(x => new art_detail { artiste = x.Select(p =>p.Field<string>("artiste")).First(), fp = x.Select(p=>p.Field<string>("file_path")).First(), nbr_album = x.Key.alb.Count() })
           .OrderBy(x => x.artiste)
                  select res;

The count is unfortunately completely wrong and i have no idea how to get the # of rating = 5 :(

Thanks for the help !

Edit : Here is my query to make it work :

               var table = Globals.ds.Tables[0].AsEnumerable();
               var stats = table.GroupBy(x => x.Field<int>("Artist_ID"))
                .Select(x => new art_detail
                {
                     artiste = x.Select(p=>p.Field<string>("artiste")).First(),
                     nbr_album = x.Select(y => y.Field<string>("album")).Distinct().Count(),
                     fp = x.Select(y => y.Field<string>("file_path")).FirstOrDefault(),
                     nbr_song = x.Count(),
                     nbr_rat5 = x.Count(y => y.Field<int>("Rating") == 5)
                 });

Simpler than what i thought :)


回答1:


Assuming a table whose schema matches this class:

public class Song
{
    public string ArtistID { get; set; }
    public string Album { get; set; }
    public string FilePath { get; set; }
    public int Rating { get; set; }
}

and given a LINQ source, you have the following query:

IQueryable<Song> table = /*insert source*/;
var stats = table.GroupBy(x => x.ArtistID);
                 .Select(x => new art_detail
                 {
                     artiste = x.Key,
                     nbr_album = x.Select(y => y.Album).Distinct().Count(),
                     nbr_song = x.Count(),
                     nbr_rat5 = x.Count(y => y.Rating == 5),
                 });



回答2:


I used head compiled query as it seemed more understandable for me in this case:

Example model:

public class Artist
{
    public string ArtistID { get; set; }
    public string Album { get; set; }
    public string FilePath { get; set; }
    public int Rating { get; set; }
    public int NumberOfSongs { get; set; }
}

Creating some dummy records for Usher and Beyonce:

//Usher
var artistOne = new Artist() 
{
    ArtistID = "Usher",
    Album = "Lit",
    FilePath = "dummy/path/here",
    Rating = 5,
    NumberOfSongs = 9
};
var artistTwo = new Artist() 
{
    ArtistID = "Usher",
    Album = "Sick",
    FilePath = "dummy/path/here",
    Rating = 5,
    NumberOfSongs = 11
};
var artistThree = new Artist() 
{
    ArtistID = "Usher",
    Album = "Dope",
    FilePath = "dummy/path/here",
    Rating = 4,
    NumberOfSongs = 14
};

//Beyonce
var artistFour = new Artist() 
{
    ArtistID = "Beyonce",
    Album = "Hot",
    FilePath = "dummy/path/here",
    Rating = 5,
    NumberOfSongs = 8
};
var artistFive = new Artist() 
{
    ArtistID = "Beyonce",
    Album = "Fire",
    FilePath = "dummy/path/here",
    Rating = 4,
    NumberOfSongs = 16
};

var listOfArtist = new List<Artist> { artistOne, artistTwo, artistThree, artistFour, artistFive };

Running query:

var result =  from a in listOfArtist
              where a.Rating == 5
              group a by a.ArtistID into art
              select new
              {
                 artist = art.Key,
                 numberOfAlbums = art.Count(),
                 numberOfSongs = art.Sum(d => d.NumberOfSongs),
              }; 

Results:

Hope this helps =)



来源:https://stackoverflow.com/questions/62398248/linq-counting-second-grouping-and-counting-without-grouping

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!