none
Group by condicional RRS feed

  • Pregunta

  • Buenas,

    os cuento lo que trato de hacer. Pretendo crear una consulta con Linq to SQL que devuelva una serie de resultados agrupados. Concretamente, se trata de una consulta sobre facturación en la que necesito sumarizar totales por días/semanas/meses/trimestres/años, siendo el periodo un parámetro de modo que la consulta Linq sea común independientemente de la periodicidad elegida. A continuación dejo mi consulta Linq, tal y como la he planteado:

    var cobros = from c in entidades.VistaCobros.DefaultIfEmpty()
                             group c by (periodo == Periodos.Diario) ? c.Fecha.Date :
                                              periodo == Periodos.Semanal ? c.Fecha.Date.AddDays(-(double)c.Fecha.DayOfWeek) :
                                              periodo == Periodos.Mensual ? new DateTime(c.Fecha.Year,c.Fecha.Month ,1) :
                                              periodo == Periodos.Trimestral ? new DateTime(c.Fecha.Year, c.Fecha.Month - (c.Fecha.Month % 3) +1, 1) :
                                              periodo == Periodos.Anual ? new DateTime(c.Fecha.Year, 1, 1) : inicio into Periodos
                             select new
                             {
    
                                 periodo = Periodos.Key,
                                 Total = Periodos.Sum(c => c.Cantidad)
                             };

    En primer lugar, supongo que desde el punto de vista de la eficiencia, sería mejor traducir los periodos a numeros enteros en vez de a fechas para sobrecargar menos el servidor (SQL Server) y hacer la traducción dinal de periodos a intervalos de fechas en el cliente. No obstante, este es mi punto de partida. Cuando hago una agrupación por trimestres, por ejemplo, tengo lo siguiente:

     periodo == Periodos.Trimestral ? new DateTime(c.Fecha.Year, c.Fecha.Month - (c.Fecha.Month % 3) +1, 1)

    Lo cual se traduce en que cada fecha referia a un trimestre, se traduce en el día 1 del mes de inicio de dicho trimestre. Por ejemplo: 20/1/2012, 12/2/2012 ó 7/3/2012 se traducirían a 1/1/2012, resultanpdo en que los totales para dichas fechas se agruparían y sumarizarían efectivamente en el primer trimestre. Por un lado tengo dudas en cuanto a la eficiencia de la consulta Linq to SQL así construida. Aún suponiendo que la consulta es correcta desde el punto de vista de la eficiencia, aún me quedaría otra duda, con respecto a la agrupación semanal:

    periodo == Periodos.Semanal ? c.Fecha.Date.AddDays(-(double)c.Fecha.DayOfWeek) :

    Realmente no estoy agrupando por semanas correctamente, porque estoy agrupando las fechas de tal forma que todos los días de cada semana se agrupan sobre el domingo de la semana correspondiente, ya que DayOfWeek enumera los días de la semana empezando en Domingo. ¿Como puedo obtener una agrupación pro semanas de Lunes a Domingo?

    Gracias por vuestra colaboración.


    • Editado FranCD lunes, 20 de febrero de 2012 11:25
    lunes, 20 de febrero de 2012 11:07

Todas las respuestas

  • ¿Qué te parece así?

    periodo == Periodos.Semanal ? c.Fecha.Date.AddDays(1-(int)c.Fecha.DayOfWeek)


    Si la respuesta te ha servido, márcala como útil.

    • Propuesto como respuesta Yván Ecarri lunes, 20 de febrero de 2012 16:11
    • Votado como útil Yván Ecarri lunes, 20 de febrero de 2012 16:12
    • Propuesto como respuesta JA Reyes miércoles, 22 de febrero de 2012 10:11
    lunes, 20 de febrero de 2012 15:32
  • Ok, podria ser una posibilidad pero

    • Miercoles, 8 de febrero de 2012, tenemos que DayOfWeek = 3, resulta en:
    • --> (8 de febrero).AddDays(1-3) --> 8-2 = 6 --> Lunes, 6 de Febrero de 2012. Correcto.
    • Domingo, 12 de febrero de 2012, tenemos que DayOfWeek = 0, resulta en:
    • --> (12 de febrero).AddDays(1-0) --> 12 + 1 = 13 --> Lunes, 13 de febrero de 2012. Incorrecto.

    Por lo tanto, no es una solución válida porque lleva los domingos hacia el Lunes de la semana próxima en vez de hacia el lunes de la semana a la que pertenecen.

    De todas formas, voy a intentarlo por ese camino haciendo algunos cambios y te comento. Gracias

    lunes, 20 de febrero de 2012 16:16
  • Ok, finalmente he conseguido algo que parece que funciona, adaptado un poco tu propuesta:

    c.Fecha.Date.AddDays(c.Fecha.DayOfWeek == DayOfWeek.Sunday ? -6 : DayOfWeek.Monday - c.Fecha.DayOfWeek);

    Saludos.

    • Propuesto como respuesta JA Reyes miércoles, 22 de febrero de 2012 10:11
    lunes, 20 de febrero de 2012 16:51