none
Consulta Linq con count y having RRS feed

  • Pregunta

  • Hola buen día a todos. Estoy haciendo unos reportes de practica tratando de entender LINQ, ya le estuve revisando pero no logro dar con la consulta real.

    Lo que quiero es obtener de mis tablas, los 5 productos con mas ventas y el numero de veces que fue hecha la compra, ya logre hacerlo en SQL, pero no logro que me de en LINQ, pueden apoyarme? Mi consulta en SQL es:

    Select pr.IdProducto,pr.Nombre, count(ve.IdVenta) as Ventas
    from Producto pr inner join DetalleVenta dv
    on pr.IdProducto=dv.IdProducto
    inner join Venta ve on dv.IdVenta=ve.IdVenta
    where dv.Status!='Cancelado'
    group by pr.IdProducto,pr.Nombre
    having COUNT(ve.IdVenta)>0
    order by pr.IdProducto

    Mi intento en LINQ es:

    var list = (from pr in Producto
             join dv in DetalleVenta
             on pr.IdProducto equals dv.IdProducto
             join ve in Venta
             on dv.IdVenta equals ve.IdVenta
             where dv.Status != "Cancelado"
             group pr by new { pr.IdProducto, pr.Nombre }into g
                           orderby g.Key.Nombre descending
                           select (new ViewModVtas5
                           {
                            NombreProducto = g.Key.Nombre,
                            Ventas = g.Count(o=>o.IdProducto)
                            })).Take(5).ToList();

    La vista me da 5 productos que no son los mas vendidos, entiendo que no tengo bien mi linq, ya que donde me confundo es para hacer el order by y el count. Espero puedan apoyarme. Gracias

    Saludos

    miércoles, 12 de noviembre de 2014 1:13

Todas las respuestas

  • No uso LINQ to SQL así que tal vez no soy la mejor autoridad, pero tanto su SQL como su LINQ se ven mal porque no ordenan de forma descendente por el total de ventas.  Su SQL ordena por ID de producto y carece de la cláusula TOP 5; su LINQ ordena por nombre y no por el total de ventas.  ¿Cómo corregir?  No sé, tendría que aprender la sintaxis y pues tal vez es mejor dejarlo como ejercicio o esperar a un experto en LINQ to SQL. :-)

    Jose R. MCP
    Code Samples

    miércoles, 12 de noviembre de 2014 1:30
  • Productos			
    IdProducto	Nombre	Categoria	Precio
    1	          Frijol	1	12
    2	          Tomate	1	11
    3	           Arroz	1	14
    4	           Aceite	1	25
    5	           Maiz 	1	6
    6	           Limon	1	9
    7	           Huevo	1	26
    8	           Cebolla	1	14
    9	           Romanita	1	23
    10	           Zanahoria	1	17
    
    Venta		
    IdVenta	Fecha	Status
    1	01/01/2014	Cancelado
    2	02/01/2014	Emitido
    3	02/01/2014	Emitido
    4	02/01/2014	Emitido
    5	03/01/2014	Emitido
    6	03/01/2014	Emitido
    7	05/01/2014	Cancelado
    8	05/01/2014	Emitido
    9	08/01/2014	Emitido
    10	08/01/2014	Emitido
    
    
    DetalleVenta				
    IdDetalleVenta	Idventa	IdProducto   Status  Observacion
    1               	2	1    Emitido Observacion1
    2	                3	1    Emitid  Observacion2
    3	                4	4    Emitido Observacion3
    4	                5	5    Emitido Observacion4
    5	                6	6    Emitido Observacion5
    6	                7	1    Cancelado	Observacion6
    7	                8	9    Emitido   Observacion7
    8	                9	4    Emitido	Observacion8
    9	                10	8    Emitido	Observacion9
    
    
    Resultado			
    IdProducto	Nombre	NumVecesVendido	
    1	          Frijol	2	
    4	          Aceite	2	
    5	          Maiz          1	
    6	          Limon	        1	
    9	          Romanita	1	
    
    

    Hola José gracias por contestar y es correcto no conozco mucho de linq y sql, estoy en mi proceso de aprendizaje. En si lo que requiero es una consulta que me cuente los números de veces que se hace un pedido de cierto producto, anexo mis tablas con algunos datos:

    Gracias por su gran y labiosa ayuda

    Saludos

    miércoles, 12 de noviembre de 2014 5:41
  • >> Lo que quiero es obtener de mis tablas, los 5 productos con mas ventas y el numero de veces que fue hecha la compra

    Como indica webJose, la consulta SQL no devuelve los 5 productos más vendidos. La SQL debería ser:

    Select TOP 5 pr.IdProducto,pr.Nombre, count(ve.IdVenta) as Ventas
    from Producto pr inner join DetalleVenta dv
    on pr.IdProducto=dv.IdProducto
    inner join Venta ve on dv.IdVenta=ve.IdVenta
    where dv.Status!='Cancelado'
    group by pr.IdProducto,pr.Nombre
    order by count(ve.IdVenta) DESC


    En este caso, la consulta LINQ debería ser tal que así:

    var list = (from pr in Producto
             join dv in DetalleVenta
             on pr.IdProducto equals dv.IdProducto
             join ve in Venta
             on dv.IdVenta equals ve.IdVenta
             where dv.Status != "Cancelado"
             group pr by new { pr.IdProducto, pr.Nombre }into g
                           select (new ViewModVtas5
                           {
                            NombreProducto = g.Key.Nombre,
                            Ventas = g.Count(o=>o.IdProducto)
                            })).OrderByDescending(x => x.Ventas).Take(5).ToList();

    La clave está en el "OrderByDescending", que hay justo antes del Take. Esto hará que los más vendidos estén los primeros de la lista.

    Estabas muy cerca ;)

    PD: Perfecto ese "ToList()" al final. Muy importante para evaluar la expresión LINQ y obtener el listado final.

    miércoles, 12 de noviembre de 2014 9:39
  • Hola Sergio gracias por contestar, de hecho el Ventas = g.Count(o=>o.IdProducto)

    Ya lo había intentado, pero me marca estos errores:

    Cannot implicity convert type 'int' to bool

    Error 4 Cannot convert lambda expression to delegate type 'System.Func<Ventas.Models.Producto,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type

    Me llama la atención, por que mi código de mi ViewModVtas5 es:

    public class ViewModVtas5     {
            public string NombreProducto { get; set; }
            public int Ventas { get; set; }
           
        }

    Se supone que Ventas = g.Count(o=>o.IdProducto), me regresa un número entero de los registros contados, no se por que me maneja bool.

    Gracias por la ayuda

    Saludos

    miércoles, 12 de noviembre de 2014 18:32
  • Mea culpa por no pasarlo por el VS Prueba directamente con g.Count(), esto te contará todos los elementos del grupo.
    miércoles, 12 de noviembre de 2014 19:17