Autor Tema: Consulta en MySQL  (Leído 1921 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Consulta en MySQL
« en: Noviembre 13, 2012, 03:03:36 pm »
¡Hola!
Estoy tratando de hacer una consulta a un servidor MySQL desde VB6.
Les comento la estructura de la base inherente a esta cuestión.
Tablas:
articulos (id, descripcion...)
listasprecios (id, descripcion...)
preciosarticulos (idarticulo, idlistaprecios, precio, iva...)
facturascompra (id, fecha...)
facturascomprad (idfactura, idarticulo, cantidad...)
Para obtener un listado de artículos con sus precios (seleccionando el id de la lista de precios desde un ComboBox y poniéndolo en la variable "listaPrecios") hago lo siguiente:

Código: Visual Basic
  1. SELECT articulos.descripcion, articulos.codigo, preciosarticulos.*
  2. FROM articulos LEFT JOIN preciosarticulos ON
  3.          (articulos.id = preciosarticulos.idarticulo AND preciosarticulos.idlistaprecios = " & listaPrecios & ")
  4. ORDER BY articulos.descripcion
  5.  

Esto anda bien. Pero ahora necesito incorporar en el listado el precio de la última compra de cada artículo. Como no sé hacerlo, lo que hice (perdón por la burrada) es lo siguiente: en cada vuelta del bucle con el que lleno el ListView hago otro query en otro recordset donde busco la información del precio de la última compra
Código: Visual Basic
  1. SELECT precio
  2. FROM facturascomprad, facturascompra
  3. WHERE facturascompra.id = facturascomprad.idfactura AND facturascompra.idarticulo = " & Tabla1!idarticulo & "
  4. ORDER BY facturascompra.fecha DESC LIMIT 1")
  5.  
¿Puedo hacer todo en la misma consulta, es decir, combinar las dos?
Muchas gracias.

Jerónimo

EDITO: Edite tu codigo para hacer mas legible la lectura, por favor siempre identalo y usa las etiquetas CODE y /CODE
Gracias.
Ahora vere tu codigo y ver si tengo algo para ayudarte. Saludos

EDITO: tenés razón, lo olvidé. Perdón y gracias.

Jerónimo
« última modificación: Noviembre 13, 2012, 06:49:15 pm por Jeronimo »

YAcosta

  • Moderador
  • Exabyte
  • *****
  • Mensajes: 2278
  • Reputación: +126/-33
  • Daddy de Qüentas y QüeryFull
    • Ver Perfil
    • Personal
Re:Consulta en MySQL
« Respuesta #1 en: Noviembre 17, 2012, 02:08:06 am »
Bueno yo no pude ayudarte mucho porque no me quedó claro el manejo que haces con el combobox, es decir, si tienes una tabla donde tienes los precios de compra y quieres obtener la ultima, pues lo primero que se me viene a la mente es usar Max(Id) de dicha tabla... pero estoy pecando de desinformado puesto que no consigo entender por mas que releo, sorry tuve broncas con clientes que son duros de matar, a ver si mañana mas tranqui la capto, por alli que una ayudita visual ayude con las pantallas y como lo quieres ver.
Me encuentras en YAcosta.com

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #2 en: Noviembre 17, 2012, 03:01:04 pm »
Hola, Yván. No problem!
Releyendo vi que no fui muy claro. A ver si puedo expresarme mejor.
Tengo una tabla maestra de artículos (articulos). Hay otra que contiene los tipos de listas de precios (de venta)  para seleccionar según el cliente (listasprecios). Los tipos de listas de precios pueden ser, por ejemplo, "público en general", "profesional", "redistribuidor". Y hay otra tabla donde establezco la relación entre los artículos y las listas de precios y almaceno los precios de venta correspondientes (preciosarticulos).
Ejemplo:
Tabla artículos.
id       Descripcion
1        Zapato
2        Zapatilla
3        Hojota

Tabla listasprecios.
id       Descripcion
1        Público
2        Distribuidor

Tabla preciosarticulos (son precios de venta).
idarticulo    idlistaprecios    precio
1                1                       20
1                2                       16
2                1                       30
2                2                       25
3                1                       18
3                2                       15

Luego están las tablas de maestro y detalle de facturas de compra.
Tabla facturascompra.
id    fecha            tipo    numero
1    xx/xx/xxxx     A        00000001
2    xx/xx/xxxx     B        00000001
3    xx/xx/xxxx     A        00000002

Tabla facturascomprad (detalle).
idfactura    idarticulo    cantidad    preciocompra
1                1                10             10
1                2                15             14
2                2                12             15 (hubo un aumento con relación a la factura anterior)
3                1                8               10
3                3                5               8

En el ComboBox pongo el contenido de la tabla listasprecios para que se pueda seleccionar qué tipo de lista de precios se va a emplear en la consulta (es decir, si se van a listar todos los precios para el público o para los distribuidores, por ejemplo). Entonces cargo la descripción y en el itemdata pongo el id de la lista de precios y luego, al momento de hacer la consulta, uso ese id.
Entonces, para obtener un listado de artículos con sus precios de venta de acuerdo al tipo de lista de precios seleccionado hago lo siguiente:
Código: [Seleccionar]
"SELECT a.descripcion, a.codigo, pa.* FROM articulos AS a
LEFT JOIN preciosarticulos AS pa ON (a.id = pa.idarticulo AND pa.idlistaprecios = " & cboListasPrecios.ItemData(cboListasPrecios.Listindex) & ")
ORDER BY a.descripcion"
Supongamos que selecciono la lista de precios "público". Entonces, el resultado de la consulta debiera ser el siguiente:
Artículo       Precio
Zapato       20
Zapatilla     30
Hojota        18

El problema viene aquí: necesito que, además de mostrar la descripción de cada artículo con su correspondiente precio de venta (de acuerdo a la lista de precios seleccionada), se muestre el precio que figura en la última factura de compra que incluya a cada artículo. Esto es para que cuando se mire una lista de artículos con precios de venta, también se pueda saber a cuánto se pagó cada uno en la última factura de compra.
Creo que ahora va mejor. Si no, cualquier cosa, me chiflan.
¡Muchas gracias!

YAcosta

  • Moderador
  • Exabyte
  • *****
  • Mensajes: 2278
  • Reputación: +126/-33
  • Daddy de Qüentas y QüeryFull
    • Ver Perfil
    • Personal
Re:Consulta en MySQL
« Respuesta #3 en: Noviembre 17, 2012, 04:16:00 pm »
Ok, ahora si te entendi ferpectamente.

Pregunta: ¿Como sabes cual es la ultima compra? Parece una pregunta tonta pero fíjate.

Si decimos que es por fecha de compra y tomo la ultima fecha, entonces ¿que pasaria con un producto que se compro 2 veces en el mismo dia?. Si no se compra en el mismo dia la cosa se resuelve facil, si no, entonces tomariamos por el Id de compra, y aqui viene la segunda pregunta ¿Ingresan las compras cronologicamente? porque pueden tener estos ingresos del producto A (mostrare solo cabecera)

id    fecha            tipo    numero
11    10/11/2012     A        00000035
14    11/11/2012     B        00000043
17    09/11/2012     A        00000024

Tendríamos que preguntar por id y fecha... para no enredar mas aclárame esos puntillos, por lo pronto la solución mas rápida hasta darle una buena pensadita es hacer un max de la compra pero dentro de un Select que estará en tu Select principal pero que dicho Select debe darte un solo valor. Ejemplo
Select A, B, (Select Max(D) From Tabla Where Dato1 = Dato2), C
From Tabla1, ...
Where ....

otra solución (que yo uso para otros fines) es tener en el maestro del producto (que alli lo tengo) o en una tabla aparte el ultimo precio de compra, es decir, cuando viene una nueva compra actualizo ese valor, de esa forma lo tomas directamente de tu misma tabla Artículos.


Otra cosa fuera de tu pregunta, por curiosidad y que quizá no has contemplado o quizá si lo contemplas pero no lo mencionas y es sobre lo siguiente:
Dices que quieres mostrar el ultimo precio de compra para saber cuanto se pago por cada articulo... ¿para que?. Te comento esto porque en el mercado donde yo implemento mi software, el cliente siempre me pide exactamente eso. El dice: ¿Quiero ver el ultimo precio de compra para poder saber hasta cuanto bajarle el precio al cliente?.
Es entonces donde le explico que lo que pide es incorrecto, lo que el debe fijarse es en el costo del articulo no en el ultimo precio de compra porque Precio de Compra no es lo mismo que Costo ¿estamos claros en eso?. Solo es lo mismo si siempre compras al mismo precio. Ahora, quizá no estas manejando "costeos" y le indicas al cliente que el ultimo precio de compra es su costo, entonces allí te indico que tengas cuidado porque puedes tener una patinada ya que dicha afirmación es un error.

Me comentas, Saludos
Me encuentras en YAcosta.com

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #4 en: Noviembre 19, 2012, 10:51:07 am »
Hola, Yván.
Muchas gracias por estar siempre ayudándome y esclareciendo muchas cosas que habitualmente no veo.
Lo he resuelto de la siguiente manera, siguiendo tu consejo (la consulta era más compleja que lo que planteé en un comienzo):
Código: Visual Basic
  1. Select a.descripcion, a.codigo, r.descripcion AS descrubro, sr.descripcion AS descsubrubro, pa.*,
  2.      (SELECT fcd.costo
  3.       FROM facturascomprad AS fcd, facturascompra AS fc
  4.       WHERE fcd.factura = fc.id AND fcd.articulo = a.id
  5.       ORDER BY fc.fecha DESC, fc.id DESC LIMIT 1) AS preciocosto
  6. FROM rubros AS r, subrubros AS sr, articulos LEFT JOIN preciosarticulos AS pa ON (a.id = pa.articulo and pa.listaprecios = " & listaPrecios & ")
  7. WHERE (a.descripcion like '%" & txtBuscar.Text & "%' OR a.codigo like '%" & txtBuscar.Text & "%')
  8. AND a.rubro = r.id AND a.subrubro = sr.id
  9. ORDER BY a.descripcion
  10.  
Lo que mencionás acerca del ingreso de las facturas de compra es un buen punto. En lugar de lo que hice podría ordenar las facturas por fecha, tipo y número para establecer cuál es la última.
Ahora, solo el proceso de consulta a la base de datos (antes de comenzar a llenar el listview) tarda 20 segundos aproximadamente. Son un poco más de 2000 artículos. Me parece mucho tiempo. A lo mejor la estoy embarrando con esto de combinar las consultas y tal vez debiera hacer como vos, que ponés el campo del último precio de compra en el maestro de artículos (o en stock). ¡Es una buena idea!
Otro buen punto es la diferencia entre costo y último precio de compra. Si quisiera tener el costo sería más fácil, incluso tal vez más rápido.
A riesgo de ser reiterativo, estoy muy agradecido por tu ayuda, Yván. Siempre te tomás tu tiempo para aclarar dudas con mucho detalle y pensando más allá del punto en cuestión.
Gracias, hermano.

Jerónimo
« última modificación: Noviembre 19, 2012, 01:03:09 pm por YAcosta »

YAcosta

  • Moderador
  • Exabyte
  • *****
  • Mensajes: 2278
  • Reputación: +126/-33
  • Daddy de Qüentas y QüeryFull
    • Ver Perfil
    • Personal
Re:Consulta en MySQL
« Respuesta #5 en: Noviembre 19, 2012, 12:59:30 pm »
Claro, es que efectivamente un Select dentro de otro Select no es muy eficiente, por eso te comente que era una primera ocurrencia mientras salga la solución optima. Yo uso esta opción cuando se trata de consulta a tablas con poquísimos registros.

Otra cosa mas que relentiza la consulta es que en el primer select pones pa.* , el * siempre sera mas lento que nombrar los campos.

Para el alias no es necesario poner As, por ejemplo puede quedar asi ..., facturascomprasd fcd, ...

Por lo demás agradezco tu agradecimiento.

Luego de revisar tu código y con la info que brindas podria decirte que en el sentido que le quieres dar a esa consulta la cosa no escalara bien. Te sugiere que hagas la modificación que te indique, si te fijas no es mucha chamba.
1.- Crea un campo llamado UltimaCompra en tu tabla articulos
2.- Corre un query que te saque la ultima compra de cada articulo de la tabla facturacomprad y actualiza la tabla articulos en el campo UltimaCompra, lo puedes hacer desde el motor, si no, lo haces desde el aplicativo con un for next para recorrer todos los artículos, extraes la ultima compra de la tabla fcd y la actualizas en la tabla artículos.
3.- Agrega en tu modulo de compra (o ingreso de mercadería) una linea de actualización de ultima compra para la tabla artículos (en el boton donde estes grabando la compra).
4.- Modifica la consulta motivo de este post para que leas la ultima compra desde la tabla articulos.
5.- Compra un par de chelas y me dices donde nos encontramos para celebrar (siempre que estés en Perú porque aquí celebramos por todo  :-) )

Salvo alguna otra mejor solucion puedes ir contemplando esta.

Saludos
« última modificación: Noviembre 19, 2012, 01:23:39 pm por YAcosta »
Me encuentras en YAcosta.com

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #6 en: Noviembre 19, 2012, 01:30:17 pm »
Excelente, Yván.
Cambié lo que me sugeriste (lo del asterisco y lo de "AS") pero el tiempo de respuesta fue similar. Incluso saqué todo el segundo "select" (como si empleara el campo en el maestro de los artículos) y en lugar de tardar 17 segundos tardó 12. Igualmente me parece mucho tiempo. Pero ahí ya no sé cómo reducirlo. Así que creo que lo voy a hacer finalmente así, con el campo del último precio de costo en el maestro de artículos, aun cuando la consulta siga siendo lenta (aunque no tanto como antes).
Muchas gracias.

Jerónimo

YAcosta

  • Moderador
  • Exabyte
  • *****
  • Mensajes: 2278
  • Reputación: +126/-33
  • Daddy de Qüentas y QüeryFull
    • Ver Perfil
    • Personal
Re:Consulta en MySQL
« Respuesta #7 en: Noviembre 19, 2012, 02:28:33 pm »
No debería tardar tanto si ya quitaste el select, algo esta mal alli, 12 segundos me demoro cuando consulto miles de registro. Como sabemos que MySQL no es mas lento que Firebird (motor que uso) quiere decir entonces que algo anda mal en la BD. Quizá te falta poner indices a las tablas (creo que en MySQL se puede, no estoy seguro pq no lo uso), tu estas haciendo consulta a 2 o 3 tablas, no debería demorar tanto. La verdad lo tuyo no deberia tardar ni un segundo.

Divide y venceras.

Haz un select simple a tu tabla articulos, deberia cargar en menos de 1 segundo.
Ve armando tu consulta y ejecutándola por partes para que veas donde ocurre la demora.

Nos comentas
Me encuentras en YAcosta.com

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #8 en: Noviembre 19, 2012, 04:28:53 pm »
¡Encantadísimo celebraría contigo si nos encontráramos en algún lugar!
Limpié la consulta y empecé desde cero: buscando en el maestro de artículos tardó menos de un segundo; lo mismo sucedió cuando agregué los rubros y subrubros. Cuando agregué los precios (incluso, sin el asterisco y poniendo un solo campo de esa tabla) tardó entre 8 y 10 segundos. Pero ahí ya no sé cómo solucionarlo. Seguramente esté mal la estructura de la base y no debiera tener las tablas así, pero fue la única forma que se me ocurrió para poder asignar a cada artículo un precio distinto de acuerdo a las listas de precios que se vayan creando.
Esta consulta tarda menos de un segundo:
Código: [Seleccionar]
"Select articulos.descripcion, articulos.codigo, rubros.descripcion descrubro, subrubros.descripcion descsubrubro
FROM articulos LEFT JOIN rubros ON articulos.rubro = rubros.id LEFT JOIN subrubros ON articulos.subrubro = subrubros.id
WHERE (articulos.descripcion like '%" & txtBuscar.Text & "%' OR articulos.codigo like '%" & txtBuscar.Text & "%') order by articulos.descripcion"
Y esta es la que tarda más tiempo:
Código: [Seleccionar]
"Select articulos.descripcion, articulos.codigo, rubros.descripcion descrubro, subrubros.descripcion descsubrubro, preciosarticulos.precio
FROM articulos LEFT JOIN rubros ON articulos.rubro = rubros.id LEFT JOIN subrubros ON articulos.subrubro = subrubros.id
LEFT JOIN preciosarticulos ON articulos.id = preciosarticulos.articulo AND preciosarticulos.listaprecios = 2
WHERE (articulos.descripcion like '%" & txtBuscar.Text & "%' OR articulos.codigo like '%" & txtBuscar.Text & "%')
ORDER BY articulos.descripcion"
¿Se te ocurre por qué puede ser que tarde tanto al agregar el precio?

seba123neo

  • Terabyte
  • *****
  • Mensajes: 744
  • Reputación: +83/-5
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #9 en: Noviembre 19, 2012, 05:01:12 pm »
me ha pasado que a veces un LEFT JOIN te traba la consulta y con INNER JOIN pasa increiblemente rapido, proba eso.
Quien nunca ha cometido un error nunca ha probado algo nuevo - Albert Einstein

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #10 en: Noviembre 19, 2012, 05:37:50 pm »
¡Muchas gracias, seba123neo!
Lo que sucede es que no todos los artículos tienen un rubro o un subrubro especificados. Y hasta donde tengo entendido, el INNER JOIN en este caso me traería todos los artículos que tengan rubro o subrubro y no traería los que no los tienen.
¿Es así?

seba123neo

  • Terabyte
  • *****
  • Mensajes: 744
  • Reputación: +83/-5
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #11 en: Noviembre 19, 2012, 06:08:12 pm »
si asi es, tambien pienso lo que dijo YAcosta que pueden ser indices, los indices te pueden llegar a bajar una consulta de un minuto a 1 segundo, pero la consulta es bastante corta, o sea no enlaza muchas tablas y tendria que ser bien rapida.

estaria bueno que capas pases la base de datos si no te importa y podria verla para optimizar esa consulta, estoy seguro que debe ser una tonteria, o sino podes subir un script con los datos de las 3 tablas que estas usando ahi, asi la creo aca en el servidor mio y lo veo, como quieras.
Quien nunca ha cometido un error nunca ha probado algo nuevo - Albert Einstein

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #12 en: Noviembre 19, 2012, 06:34:11 pm »
¡Eso me vendría genial!
Ahora estoy saliendo apuradísimo, pero en cuanto vuelva lo pondré aquí para que puedas analizarlo.
¡Muchas gracias!

Jerónimo

Jeronimo

  • Gigabyte
  • ****
  • Mensajes: 285
  • Reputación: +29/-2
    • Ver Perfil
Re:Consulta en MySQL
« Respuesta #13 en: Noviembre 20, 2012, 12:59:31 am »
seba123neo: hice un backup de las tablas, pero no sé cómo ponerlo aquí en el foro y no tengo cuenta en ninguno de los servidores como Megaupload, etc. ¿Puedo mandarte el archivo a tu mail para que lo veas, o, en todo caso, lo subas por si alguien más quiere darle una mirada?
Muchas gracias.

Jerónimo

YAcosta

  • Moderador
  • Exabyte
  • *****
  • Mensajes: 2278
  • Reputación: +126/-33
  • Daddy de Qüentas y QüeryFull
    • Ver Perfil
    • Personal
Re:Consulta en MySQL
« Respuesta #14 en: Noviembre 20, 2012, 01:12:21 am »
Jeronimo, hagamosnos un favor y ganemos 500 megas adicionales cada uno. Para lo que quieres hacer puedes usar Dropbox registrandote con este enlace:
http://db.tt/V7LZalpp

Cuando entres alli te registras con tu correo, creas una cuenta, te bajas el aplicativo y luego ya podrás compartir archivos y tener enlaces web directos a los archivos que publicas.

Te aclaro que lo que lograras será un espejo de lo que tengas en tu carpeta local en tu cuenta dropbox, osea si borras algo alli se borra en la nube y viceversa, si agregas algo alli se agrega en la nube, si apagas tu pc no se borra nada.
Aqui un ejemplo de como compartir un archivo:


Luego que chequees la web veras que haciendo cuando consigas que otras personas usen dropbox con tu refer, tu conseguiras 500 mb de espacio adicional y el limite son 16gb GRATIS.

¿Donde esta la practicidad? que pones el archivo en tu carpeta local y dejas que este suba ya que el programa de dropbox esta corriendo en segundo plano, incluso cuando lo pones en tu carpeta local ya puedes obtener el enlace que es el que enviarias a quien desees, el que tenga el enlace podra descargar el archivo y nada mas, no a los otros archivos salvo que compartas la carpeta. Y si estas en otro sitio puedes subir via web el archivo a tu cuenta de dropbox y cuando llegues a tu casa dicho archivo ya estara en tu disco local (obviamente si esta la pc prendida, sino esperas cuando la prendas los archivos se iran descargando)

Entonces la BD la pones en la carpeta local de dropbox y nos mandas el enlace a dicho archivo.

Saludos
Saludos
« última modificación: Noviembre 20, 2012, 01:28:10 am por YAcosta »
Me encuentras en YAcosta.com