简体   繁体   中英

How to SUM up results by column value in db query result

My database has a sales table with entries like so:

_____________________________________
| id |  title_id   |       qty      |
-------------------------------------
| 0  |  6          |        10      |
-------------------------------------
| 1  | 5           |        5       |
-------------------------------------
| 2  |  6          |        2       |
-------------------------------------

Title_id is Foreign key pointing to Titles table which is as follows:

_____________________________________
| id |  title_id   |       title    |
-------------------------------------
| 0  |  5          |       Soda     |
-------------------------------------
| 1  |  6          |      Coffee    |
-------------------------------------

I want to find top 5 sold products wich means i need to calculate the qty value for each product for all it's entried in sales table then order the result by qty in descending order and limit the select to 5.

However I'm new to C# ASP.NET and somewhat new to SQL. I dont know how to do this with LINQ. This is my code so far:

        var getIds = (from sale in db.sales
                      join tit in db.titles on sale.title_id equals tit.title_id
                      group sale by sale.qty into result
                      orderby result.Sum(i => i.qty) descending
                      select new Publication 
                      { 
                        PubID = sales.title_id, Title = tit.title
                      }
                      ).Take(5);

Assuming you have a navigation property Sale.Title , something like this should do:

var tops = 
  db.Sales
    .GroupBy( o => o.Title )
    .Select( o => new { Title = o.Key, Sum = o.Sum( x => x.Quantity ) } )
    .OrderByDescending( o => o.Sum )
    .Take( 5 )
    .ToList();

tops is then a list of an anonymous type with two properties: the Title object and the sum of the quantities.


You can then get the values like this:

foreach( var top in tops )
{
  int titleId = top.Title.title_id;
  string title = top.Title.title;
  int sumOfQuantities = top.Sum;
  ...

If you just want the top Title objects, can can select them like this:

List<Title> topTitles = tops.Select( o => o.Title ).ToList();
var result= (from p in sales
              let k = new
              {
                  Name = p.Name
              }
              group p by k into t
              orderby Name descending
              select new
              {
                  Name = t.Name,
                  Qty = t.Sum(p => p.Qty)
              }).Take(5);

If the entries in the Sales table are more than one per item (ie: in your example you have 'Soda' 10 + 'Soda' 2, then you need to GroupBy() , using the name as the key (or it's related id if it's in another table), but not the qty.

var topSales = db.sales.GroupBy(x => x.title)
                       .Select(g => new 
                                    { 
                                       Title = g.Key, 
                                       Qty = g.Sum(x => x.qty)
                                    })
                       .OrderByDescending(x => x.Qty)
                       .Select(x => new Publication 
                                    { 
                                       PubID = x.Title.title_id, 
                                       Title = x.Title.title1
                                    })
                       .Take(5)
                       .ToList();

Note that I've omitted the join statement assuming that you have a foreign key between sales.title_id -> title.id, and you are using LINQ to SQL. Also note that I've avoided using the query syntax in favor of the chained method syntax, I think it's much clear in this use case (although not always true, ie: cross-joins).

Also, SQL and LINQ have some similarities but don't let the names of clauses/methods fool you, LINQ is not SQL, IMHO, Microsoft just tried to make people comfortable by making it look similar ;)

EDIT : fixed GroupBy()

var result= (from p in sales
              let k = new
              {
                  Name = p.Name
              }
              group p by k into t
              select new
              {
                  Name = t.Name,
                  Qty = t.Sum(p => p.Qty)
              }).OrderByDescending(i => i.Qty).Take(5);

You need to look at GroupBy; this will give you what you need

http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

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