1

I have a c# program that I am programing where someone inputs production for the whole day and I calculate the Machine Usage (MU) like this:

Date      | Part Number | Mold Num | Machine Num |  MU  
2/12/2016 | 1185-5B8    |  6580    | 12          |  .428            
2/12/2016 | 2249300     |  7797    | 36          |  .271            
2/12/2016 | 146865      |  5096789 | 12          |  .260            
2/16/2016 | 123456      |  7787    | 56          |  .354            
2/16/2016 | 123456      |  787     | 54          |  .45            
2/16/2016 | 123456      |  777     | 56          |  .799            
2/16/2016 | 123456      |  87      | 54          |  .611          

How would I group the data that is all in the same table like so:

2/12/2016                   2/16/2016
Machine Num. | MU           Machine Num. | MU
    12       | 34.4%            54       | 53.0%
    36       | 27.1%            56       | 57.6%

The table where everything is at is called [MU Report]

EDIT:

MU = Time Ran / Time available. So what I did was calculate MU for each individual entry to take an average of it later.

JCM
  • 151
  • 8
  • 1
    You should post what you tried to do and ask for tips if you can't proceed any more by yourself. You shouldn't ask others to do your work. – Leandro Soares Jun 21 '16 at 15:00
  • This is too broad, "There are either too many possible answers, or good answers would be too long for this format. Please add details to narrow the answer set or to isolate an issue that can be answered in a few paragraphs." – Camilo Terevinto Jun 21 '16 at 15:01
  • @LeandroSoares I dont know how to do this because everything that I looked at does it through 2 tables and this is an oversimplified version of what I actually have to do. I just wanted a basic understanding in order to do the rest. – JCM Jun 21 '16 at 15:01
  • Ok, did you try to look on other posts? – Leandro Soares Jun 21 '16 at 15:06
  • @LeandroSoares yes I did I also tried to fallow one similar post but didn't know what variables I had to change in order for it to function for me. – JCM Jun 21 '16 at 15:08
  • @JCM, i see... you are new to c# or linq/lambda – Leandro Soares Jun 21 '16 at 15:10
  • http://stackoverflow.com/questions/2421388/using-group-by-on-multiple-columns Here, you can see how you group by 2+ columns – Leandro Soares Jun 21 '16 at 15:10
  • @LeandroSoares Extremely new and was tasked with a huge project – JCM Jun 21 '16 at 15:13
  • @LeandroSoares is it possible to change the count into an average of a column? – JCM Jun 21 '16 at 15:18
  • Hmmm yes it is, i'll try to post an answer – Leandro Soares Jun 21 '16 at 15:53

2 Answers2

1

Working Demo

Class (Sample):

public class MachineData
{
    public DateTime Date { get; set; }

    public string PartNumber { get; set; }

    public int MoldNum { get; set; }

    public int MachineNum { get; set; }

    public decimal MU { get; set; }
}

Query:

var query =
    dbItems
        .GroupBy(x => new { x.Date, x.MachineNum })
        .Select(x => new
        {
            Date = x.Key.Date,
            MachineNum = x.Key.MachineNum,
            AverageMU = x.Average(i => i.MU * 100)
        })
        .ToList(); 

GroupBy(x => new { x.Date, x.MachineNum })

Here you can group all the items by Date and MachineNum

.Select(x => new
{
      Date = x.Key.Date,
      MachineNum = x.Key.MachineNum,
      AverageMU = x.Average(i => i.MU * 100)
      // Instead of x.Average you may used other functions like: Count, Any etc.
})

The following Select will create an anonymous type which will contain: Date, MachineNum and the average of MU * 100 to get the percentage.

PS: I used lambda instead of pure LINQ because i don't really like to work with LINQ

Leandro Soares
  • 2,902
  • 2
  • 27
  • 39
  • What would I replace the `dbItems` with? Would it be the name of my table that I am calling? – JCM Jun 21 '16 at 16:58
  • yes, it's your `database.TableName` are you using `entityframework`? – Leandro Soares Jun 21 '16 at 17:01
  • when i try to do the `database.TableName` it does not recognize the table but if I type in the table by itself it does but says that the table does not contain a definition for `.GroupBy`. Yes I am using `entityframework` – JCM Jun 21 '16 at 17:14
  • do: `database.` and then you need to use the following `using` `using System.Linq` – Leandro Soares Jun 22 '16 at 08:55
  • Figured out what I did wrong forgot to put the `DataContext` in. However now my `.ToList()` is not working im getting the error of missing a using directive. – JCM Jun 22 '16 at 12:46
  • Check if all brackets are ok – Leandro Soares Jun 22 '16 at 13:02
  • `var shiftreports = new LINQToSQLDataContext(); var query = shiftreports.MU_Reports .GroupBy(x => new { x.Date, x.Machine_Number }) .Select(x => new { Date = x.Key.Date, MachineNum = x.Key.Machine_Number, MU = x.Sum(i => System.Convert.ToDouble(i.MU) * 100) }) .Tolist();` It seems like they are – JCM Jun 22 '16 at 13:30
  • _'IQueryable<>' does not contain a definition for 'Tolist' and no extension method 'Tolist' accepting a first argument of type 'IQueryable<>' could be found (are you missing a using directive or an assembly reference?)_ This is the error I'm getting with it – JCM Jun 22 '16 at 13:48
  • It isn't `Tolist` it's `ToList`. And, `System.Convert.ToDouble(i.MU) * 100` will not work, you can't use c# methods inside `Lambda` / LINQ2SQL because they are not convertible to SQL – Leandro Soares Jun 22 '16 at 13:56
  • Oops. It all works now. But the system.convert had to be there because it said that mu was a string and when i put it in there it didn't come with an error – JCM Jun 22 '16 at 14:00
  • `MU` is a string? hmmm ok, tell me if the convert function works – Leandro Soares Jun 22 '16 at 14:07
  • 1
    It did but I just changed `MU` to be a float to minimize code that the next guy has to sift through. Thank you for all your help – JCM Jun 22 '16 at 14:22
0

Since the average is based on the day only and the grouping is based on both the Date and the Machine number, you need to-level grouping:

a. Calculate the Total Per each day.

b. Calculate the average per day per machine based on the above totals

var dailyTotals = sampleData.GroupBy(x => x.Date)
                            .ToLookup(x => x.Key, x => x.Sum(y => y.MU));

var groupedData = (from m in sampleData
                    group m by new { m.Date, m.MachineNum } into grp
                    let dailyTotal = dailyTotals[grp.Key.Date].FirstOrDefault()
                    let dailyMachineTotal = grp.Sum(x => x.MU)
                    select new
                    {
                        Date = grp.Key.Date,
                        MachineNumber = grp.Key.MachineNum,
                        MU = (dailyMachineTotal / dailyTotal) * 100
                    }).ToList();
Zein Makki
  • 29,485
  • 6
  • 52
  • 63
  • But you group by Date, there is no need to calculate the daily total, since all the the items provided by the group by will have the same day variable `grp` – Leandro Soares Jun 21 '16 at 16:14
  • I feel like this is just adding a step that is not needed. Taking an average of all the machines individually and doing it as you did above should yield the same answer. – JCM Jun 21 '16 at 16:52
  • @LeandroSoares But we might have items outside the grp with the same day, since they have a different Machine Number. Remember that we are grouping by two fields here. – Zein Makki Jun 22 '16 at 05:22
  • @JCM Do you have a specific formula for calculating the average ? Can you post it in the question ? I guessed from the way you organised your sample result that the average is for each machine with respect to the whole day. Please correct me if i'm wrong. – Zein Makki Jun 22 '16 at 05:26
  • In your example, you are using the daily total which will be used to determinate the total `MU` of the day. We just need to know if the `MU` is already calculated or if it needs to be calculated like you do – Leandro Soares Jun 22 '16 at 09:00