问题
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