none
Linq, calcolo percentuale RRS feed

  • Domanda

  • Tramite linq riesco a calcolare il fatturato giornaliero dell'azienda, come posso, sempre tramite linq, calcolare la variazione percentuale rispetto al giorno precedente?


    Se questo post risponde alla tua domanda ricorda di contrassegnarlo come risposta. In questo modo aiuterai altri utenti che hanno lo stesso problema a trovare la risposta più velocemente. Grazie.

    • Spostato Irina Turcu giovedì 3 ottobre 2013 17:25 Spostato il thread nel forum più appropriato all'argomento discusso.
    mercoledì 2 ottobre 2013 15:52

Risposte

  • Non avendo fornito dettagli sul tuo problema, e avendo specificato che già sapevi calcolare il fatturato giornaliero, sembrava che la tua domanda riguardasse il calcolo della variazione percentuale, non quello del fatturato per il giorno precedente.

    Nella prima query che hai mostrato calcoli l'incasso per ogni giorno. Avendo questa informazione, in realtà hai anche il fatturato del giorno precedente, anche se non "direttamente". Mi spiego: hai record per i giorni X, X + 1 e X + 2, ognuno dei quali con il fatturato giornaliero. Ma questo vuol dire che sai anche, ad esempio, il fatturato del giorno precedente a X + 1 (ti basta recuperare il fatturato di X).

    Quindi, riassumendo, puoi usare la prima query per recuperare il fatturato giornaliero giorno per giorno, dopodiché esegui una seconda query LINQ per "aggiungere" ad ogni record il valore del fatturato del giorno precedente.


    Marco Minerva [MCPD]
    Blog: http://marcominerva.wordpress.com
    Twitter: @marcominerva

    • Proposto come risposta Irina Turcu giovedì 3 ottobre 2013 17:15
    • Contrassegnato come risposta Irina Turcu mercoledì 9 ottobre 2013 19:13
    giovedì 3 ottobre 2013 08:03

Tutte le risposte

  • LINQ non ha una funzione nativa per il calcolo della variazione percentuale tra due valori, ma puoi facilmente calcolarla utilizzando la seguente formula:

    (NEW_VALUE - OLD_VALUE) / OLD_VALUE * 100

    Se è un'operazione che devi eseguire spesso, puoi creare un Extension Method ad hoc, così da rendere molto più agevole il suo utilizzo.


    Marco Minerva [MCPD]
    Blog: http://marcominerva.wordpress.com
    Twitter: @marcominerva

    mercoledì 2 ottobre 2013 16:55
  • Grazie per la risposta,

    quello sapevo farlo, il problema è l'estrazione dei dati che non riesco a fare.

    Utilizzo E.F. e ho l'oggetto Incasso definito come segue :

    public class Incasso
        {
            [Key]
            public int Id { get; set; }
    
            public string TipoMovimento{ get; set; }
    
            public DateTime Data { get; set; }
    
            public decimal Importo { get; set; }
        }

    Ora, se voglio l'incasso per ogni giorno l'espressione LINQ è molto semplice :

    from mf in db.Incassi
    where  (mf.TipoMovimento.StartsWith("Incasso"))
    group a by new { y = mf.Data.Year, m = mf.Data.Month, d = mf.Data.Day} into grp
    orderby grp.Key.y, grp.Key.m, grp.Key.d
    select new {
        Anno = grp.Key.y, 
        Mese = grp.Key.m, 
        Giorno = grp.Key.d, 
        ImportoGiornaliero = grp.Sum(a => mf.Importo)
    }

    Per avere la variazione percentuale ho questa query linq solo che non è performante, anzi, lo è tutt'altro.

    var incassi = from i in this.incassiRepo.GetOnlyIncasso()
                  group i by new { DataMov = new DateTime(i.Data.Year, i.Data.Month, i.Data.Day) } into grp
                              select new FatturatoGiornaliero
                              {
                                  Giorno = new DateTime(grp.Key.DataMov.Year, grp.Key.DataMov.Month, grp.Key.DataMov.Day),
                                  Ieri = grp.Key.DataMov.AddDays(-1),
                                  GuadagnoGiornaliero = grp.Sum(f => f.Importo),
                                  GuadagnoGiornalieroGiornoPrecedente = (from yest in this.incassiRepo.GetOnlyIncasso()
                                                                         let DataIeri = grp.Key.DataMov.AddDays(-1)
                                                                         where yest.Data.Year == DataIeri.Year && yest.Data.Month == DataIeri.Month && yest.Data.Day == DataIeri.Day
                                                                         group yest by new { yest.Data.Year, yest.Data.Month, yest.Data.Day } into grpyest
                                                                         select grpyest.Sum(f => f.Importo)).FirstOrDefault()
                              };

    Questo perchè per ogni giorno deve rifare la query per il giorno precedente.

    Posso ottimizzare in linq in qualche modo?


    Se questo post risponde alla tua domanda ricorda di contrassegnarlo come risposta. In questo modo aiuterai altri utenti che hanno lo stesso problema a trovare la risposta più velocemente. Grazie.

    giovedì 3 ottobre 2013 07:42
  • Non avendo fornito dettagli sul tuo problema, e avendo specificato che già sapevi calcolare il fatturato giornaliero, sembrava che la tua domanda riguardasse il calcolo della variazione percentuale, non quello del fatturato per il giorno precedente.

    Nella prima query che hai mostrato calcoli l'incasso per ogni giorno. Avendo questa informazione, in realtà hai anche il fatturato del giorno precedente, anche se non "direttamente". Mi spiego: hai record per i giorni X, X + 1 e X + 2, ognuno dei quali con il fatturato giornaliero. Ma questo vuol dire che sai anche, ad esempio, il fatturato del giorno precedente a X + 1 (ti basta recuperare il fatturato di X).

    Quindi, riassumendo, puoi usare la prima query per recuperare il fatturato giornaliero giorno per giorno, dopodiché esegui una seconda query LINQ per "aggiungere" ad ogni record il valore del fatturato del giorno precedente.


    Marco Minerva [MCPD]
    Blog: http://marcominerva.wordpress.com
    Twitter: @marcominerva

    • Proposto come risposta Irina Turcu giovedì 3 ottobre 2013 17:15
    • Contrassegnato come risposta Irina Turcu mercoledì 9 ottobre 2013 19:13
    giovedì 3 ottobre 2013 08:03
  • Modificando la query ho provato così, ma da risultati errati....

    var listaIncassi = movimentiIncasso.ToList();
                var incassi = from data in (from i in listaIncassi
                                              group i by new { DataMov = new DateTime(i.Data.Year, i.Data.Month, i.Data.Day) } into grp
                                              select new{
                                                  Oggi = grp.Key.DataMov,
                                                  Ieri = grp.Key.DataMov.AddDays(-1)
                                              }
                                            )
    										
    
    						from today in listaIncassi where  data.Oggi.Year == today.Data.Year &&  data.Oggi.Month == today.Data.Month && data.Oggi.Day == today.Data.Day
    						from yesterday in listaIncassi where data.Ieri.Year == yesterday.Data.Year && data.Ieri.Month == yesterday.Data.Month &&  data.Ieri.Day == yesterday.Data.Day
    
                              group new {today, yesterday} by new {
                                  Oggi = new DateTime( today.Data.Year, today.Data.Month, today.Data.Day),
                                 Ieri =  new DateTime( yesterday.Data.Year, yesterday.Data.Month, yesterday.Data.Day) 
    							 
                              } into gruppo
    						  
                              select new FatturatoGiornaliero
                              {
                                  Giorno = gruppo.Key.Oggi,
                                  Ieri = gruppo.Key.Ieri  ,
                                  GuadagnoGiornaliero = gruppo.Sum(f => f.today.Importo),
                                  GuadagnoGiornalieroGiornoPrecedente = gruppo.Sum(f =>  f.yesterday.Importo) 
                              };
    infatti m'aspettavo in GuadagnoGiornalieroGiornoPrecedente il valore GuadagnoGiornaliero della riga sopra solo che non funziona


    Se questo post risponde alla tua domanda ricorda di contrassegnarlo come risposta. In questo modo aiuterai altri utenti che hanno lo stesso problema a trovare la risposta più velocemente. Grazie.


    • Modificato bab76 giovedì 3 ottobre 2013 08:18
    giovedì 3 ottobre 2013 08:17
  • In questo caso credo sia più semplice spezzare l'algoritmo in due: prima calcoli il fatturato giornaliero per ogni giorno, ovvero esegui la prima query, e poi ad ogni riga ottenuta "aggiungi" il fatturato del giorno precedente.

    Marco Minerva [MCPD]
    Blog: http://marcominerva.wordpress.com
    Twitter: @marcominerva

    giovedì 3 ottobre 2013 08:50
  • Ok, grazie mille per la risposta, pensavo si potesse fare il tutto con un'unica query ;-) Tanto sono diventato Linq dipendente!!!

    Se questo post risponde alla tua domanda ricorda di contrassegnarlo come risposta. In questo modo aiuterai altri utenti che hanno lo stesso problema a trovare la risposta più velocemente. Grazie.

    giovedì 3 ottobre 2013 10:35