Jump to content


Photo

Consulta con 3 tablas y agrupar por dos campos


  • Please log in to reply
19 replies to this topic

#1 enecumene

enecumene

    Webmaster

  • Administrador
  • 7419 posts
  • LocationRepública Dominicana

Posted 25 October 2012 - 03:14 PM

Pues eso tengo 3 tablas:

Despachos
Vehiculos
categoria

El sistema es un control de despacho de combustibles, en la tabla despachos tiene un campo integer que indica si el combustible es gasolina o gasoil, lo que necesito es obtener un resumido del dia de los despachos realizados agrupados por categorias y tipo de combustible, algo asi:

[table]
[tr]
[td]CATEGORIA[/td]
[td][/td]
[td]GASOLINA[/td]
[td]GASOIL[/td]
[/tr]
[tr]
[td][/td]
[td][/td]
[td][/td]
[/tr]
[tr]
[td]VEHICULOS INTERNOS[/td]
[td][/td]
[td]15[/td]
[td]393[/td]
[/tr]

[tr]
[td]VEHICULOS PRIVADOS[/td]
[td][/td]
[td]120[/td]
[td]12[/td]
[/tr]
[tr]
[td]PLANTAS ELECTRICAS[/td]
[td][/td]
[td]9[/td]
[td]1340[/td]
[/tr]
[tr]
[td]PEAJES[/td]
[td][/td]
[td]0[/td]
[td]0[/td]
[/tr]
[tr]
[td]BOULEVARDS[/td]
[td][/td]
[td]0[/td]
[td]0[/td]
[/tr]
[tr]
[td]AYUDANTIAS[/td]
[td][/td]
[td]0[/td]
[td]0[/td]
[/tr]
[/table]

Con esta consulta que me proporcionó mi estimado egostar:

select
c.cat_nombre,
(select sum(d.desp_cant) from despachos d where d.desp_comb = 1 and d.ve_id = v.ve_id and d.desp_tipo = 'AN') as GASOLINA,
(select sum(d1.desp_cant) from despachos d1 where d1.desp_comb = 2 and d1.ve_id = v.ve_id and d1.desp_tipo = 'AN') as GASOIL
from categoria c
left join vehiculos v on v.ve_categoria = c.cat_id


Obtengo categorias dividas y repetidas y con valores nulo, alguien tiene una mejor idea, pues bienvenido sea :)

Saludos.
  • 0

#2 LuNaTk

LuNaTk

    Newbie

  • Miembros
  • Pip
  • 8 posts

Posted 25 October 2012 - 04:52 PM

quiza algo asi pudiera funcionar

    
SELECT
    c.cat_nombre,
    (SELECT SUM(d.desp_cant) FROM despachos d, vehiculos v WHERE d.ve_id=v.veh_id AND d.desp_comb = 1 AND v.ve_categoria=c.cat_id AND d.desp_tipo = 'AN') AS GASOLINA,
    (SELECT SUM(d1.desp_cant) FROM despachos d1, vehiculos v1  WHERE d1.ve_id=v1.veh_id AND d1.desp_comb = 2 AND v1.ve_categoria=c.cat_id AND d1.desp_tipo = 'AN') AS GASOIL
    FROM categoria c


muy seguramente no es lo más eficiente, pero a falta de conocer la estructura de las tablas y las relaciones entre ellas, por ahora no doy para más.
  • 0

#3 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 25 October 2012 - 07:02 PM

Sería más sencillo amigo si pusieras la estructura de las tres tablas :) y al menos una fila a modo de ejemplo de la información que contienen :D
  • 0

#4 William dFlota

William dFlota

    Member

  • Miembros
  • PipPip
  • 34 posts
  • LocationPerú

Posted 26 October 2012 - 08:00 AM

Hola buen día.

Es la primera vez que escribo en esta página y bien espero poder ayudarte.

Creo que sería suficiente hacer dos consultas por separado y luego unirlas con un Union o Union All según sea el caso.
Obviamente tendrías que generar consultas con la misma cantidad de columnas y del mismo tipo y nombre lo cual es un requisito indispensable para generar Union's.

Ejemplo

Select Campo1, Campo2, Campo3 = Sum(Campo3) From Tabla1
Where Condicion = ''
Union
Select Campo1, Campo2, Campo3 = Sum(Campo3) From Tabla2
Where Condicion = ''


Espero te sirva y como bien dijo alguien por ahí lo mejor hubiera sido que envíes la estructura de tus tablas.

Saludos
deCTod
  • 0

#5 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 08:03 AM

Hola buen día.

Es la primera vez que escribo en esta página y bien espero poder ayudarte.


Bienvenido amigo... es un gusto que te hayas animado a compartir conocimiento...
  • 0

#6 enecumene

enecumene

    Webmaster

  • Administrador
  • 7419 posts
  • LocationRepública Dominicana

Posted 26 October 2012 - 08:11 AM

Muchas gracias deCTod y bienvenido!, estimado poli, ahora mismo no tengo acceso al BD para darte la estructura de la misma, pero sí tengo el archivo ahora, es Firebird 2.5, si tienes como acceder con gusto lo paso, sino, si puedes esperar te paso la estructura.
  • 0

#7 William dFlota

William dFlota

    Member

  • Miembros
  • PipPip
  • 34 posts
  • LocationPerú

Posted 26 October 2012 - 08:16 AM


Hola buen día.

Es la primera vez que escribo en esta página y bien espero poder ayudarte.


Bienvenido amigo... es un gusto que te hayas animado a compartir conocimiento...


Muchas gracias por la bienvenida y espero poder ayudar a quien lo necesite y por supuesto aprender de uds. también.
Saludos
deCTod
  • 0

#8 enecumene

enecumene

    Webmaster

  • Administrador
  • 7419 posts
  • LocationRepública Dominicana

Posted 26 October 2012 - 09:44 AM

Pos aquí dejo las estructuras:

CREATE TABLE CATEGORIA (
    CAT_ID      INTEGER NOT NULL,
    CAT_NOMBRE  VARCHAR(25) NOT NULL
);

CREATE TABLE DESPACHOS (
    DESP_ID          INTEGER NOT NULL,
    VE_ID            INTEGER NOT NULL,
    DESP_TIPO        VARCHAR(5) NOT NULL,
    DESP_FECHA        DATE NOT NULL,
    DESP_HORA        TIME NOT NULL,
    DESP_CANT        NUMERIC(15,2) NOT NULL,
    DESP_COMB        INTEGER NOT NULL,
    DESP_RECIBIDO    VARCHAR(60) NOT NULL COLLATE ES_ES_CI_AI,
    DESP_CEDULA      VARCHAR(15) NOT NULL,
    DESP_ESTADO      INTEGER DEFAULT 1,
    DESP_USER        VARCHAR(15) NOT NULL,
    DESP_MARCA        VARCHAR(25) COLLATE ES_ES_CI_AI,
    DESP_MODELO      VARCHAR(25) COLLATE ES_ES_CI_AI,
    DESP_PLACA        VARCHAR(10) COLLATE ES_ES,
    DESP_VEHANIO      INTEGER,
    DESP_COLOR        VARCHAR(20) COLLATE ES_ES_CI_AI,
    DESP_KM          INTEGER DEFAULT 0,
    DESP_SOLICITADO  VARCHAR(100) COLLATE ES_ES_CI_AI,
    DESP_TRABAJOS    BLOB SUB_TYPE 1 SEGMENT SIZE 16384,
    DESP_RUTA        VARCHAR(200) COLLATE ES_ES_CI_AI,
    DESP_INTEGRANTES  VARCHAR(200) COLLATE ES_ES_CI_AI,
    DESP_CONSUMIDOR  INTEGER
);

CREATE TABLE VEHICULOS (
    VE_ID            INTEGER NOT NULL,
    TV_ID            INTEGER NOT NULL,
    VE_FICHA          VARCHAR(20) NOT NULL,
    COMB_ID          INTEGER NOT NULL,
    VE_MARCA          VARCHAR(20) NOT NULL,
    VE_MODELO        VARCHAR(20) NOT NULL,
    VE_ANIO          INTEGER NOT NULL,
    VE_COLOR          VARCHAR(15) NOT NULL,
    VE_CHASIS        VARCHAR(40) NOT NULL,
    VE_PLACA          VARCHAR(10) NOT NULL,
    VE_CONSUMIDOR    INTEGER NOT NULL,
    VE_CATEGORIA      INTEGER NOT NULL,
    VE_TIPO          INTEGER NOT NULL,
    VE_CONS_SEC      INTEGER NOT NULL,
    VE_ESTADO        INTEGER NOT NULL,
    VE_CAPACIDAD      INTEGER,
    VE_ASIGNADOA      VARCHAR(60) NOT NULL,
    VE_ASIGNADOCED    VARCHAR(15) NOT NULL,
    VE_CHOFER        VARCHAR(60),
    VE_CHOFERCED      VARCHAR(15),
    VE_ASIGNADOCARGO  VARCHAR(60) NOT NULL
);


Más abajo anexo imagen con el contenido de la tablas despachos.

Saludos.

Attached Files


  • 0

#9 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 10:02 AM

hola amigo... una pregunta que campo establece la categoria

DESP_TIPO de la tabla despachos o VE_CATEGORIA  de la tabla vehículos
  • 0

#10 enecumene

enecumene

    Webmaster

  • Administrador
  • 7419 posts
  • LocationRepública Dominicana

Posted 26 October 2012 - 10:20 AM

DESP_TIPO indica el tipo de Despacho ('AN', 'CR' y 'AE') y VE_CATEGORIA es la categoria del vehiculo.

Saludos.
  • 0

#11 William dFlota

William dFlota

    Member

  • Miembros
  • PipPip
  • 34 posts
  • LocationPerú

Posted 26 October 2012 - 11:00 AM

Hola

Sólo algunas observaciones

Por que cambiar el nombre del campo CAT_ID por VE_CATEGORIA si es una FK, la regla dice que ambos deberian de tener el mismo nombre :)

Bien ahora si procedo a darte una posible solucion

Hacemos una relación entre las tres tablas

Select * From Categoria c, Vehiculos v, Despachos D
Where c.CatId = v.VE_Categoria
And v.VE_Id = d.VE_Id


Hasta este punto sólo hemos relacionado las 3 tablas

Ahora haremos lo siguiente:

Select c.CAT_Nombre, d.DESP_Tipo, d.DESP_Comb, Sum(IsNull(d.DESP_Cant,0))
From Categoria c, Vehiculos v, Despachos D
Where c.CatId = v.VE_Categoria
And v.VE_Id = d.VE_Id
And d.DESP_Fecha Between '00/00/0000' And '00/00/0000'
Group By c.CAT_Nombre, d.DESP_Tipo, d.DESP_Comb


Bien este es el primer resultado el cual hace lo que deseas, bueno es lo que pienso deseas.

Pero según tu consulta tu necesitas que aparezca en dos columnas
Bien lo único que hacemos sería lo siguiente:

Select c.CAT_Nombre, Gasolina = Sum(IsNull(d.DESP_Cant,0)), GasOIL = 0
From Categoria c, Vehiculos v, Despachos D
Where c.CatId = v.VE_Categoria
And v.VE_Id = d.VE_Id
And d.DESP_Fecha Between '00/00/0000' And '00/00/0000'
And d.DESP_Comb = 1
And d.DESP_Tipo = 'AN'
Group By c.CAT_Nombre

UNION

Select c.CAT_Nombre, Gasolina = 0, GasOIL = Sum(IsNull(d.DESP_Cant,0))
From Categoria c, Vehiculos v, Despachos D
Where c.CatId = v.VE_Categoria
And v.VE_Id = d.VE_Id
And d.DESP_Fecha Between '00/00/0000' And '00/00/0000'
And d.DESP_Comb = 2
And d.DESP_Tipo = 'AN'
Group By c.CAT_Nombre



Bien en la primer consulta que enviaste hiciste algunas relaciones que no entiendo muy bien por la estructura "And d.DESP_Comb = 1"
pero la adicione por que es parte de tu consulta inicial.

Espero haberte ayudado
PD: Prueba con Union y Union All para que veas sus diferencias

Saludos
deCTod
  • 0

#12 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 11:03 AM




  -- como creo que firebird no soporta subconsultas usaremos
  -- unas tablas temporales

          INSERT INTO TMPDESPACHOSGASOLINA
          SELECT ve_categoria, sum(desp_cant) CANTIDAD
            FROM despachos
        LEFT JOIN vehiculos
              ON despachos.ve_id = vehiculos.ve_id 
            WHERE desp_comb = 1 AND
                  desp_tipo = 'AN'
          Group by ve_categoria 

          INSERT INTO TMPDESPACHOSGASOIL
          SELECT ve_categoria, sum(desp_cant) CANTIDAD
            FROM despachos
        LEFT JOIN vehiculos
              ON despachos.ve_id = vehiculos.ve_id 
            WHERE desp_comb = 2 AND
                  desp_tipo = 'AN'
          Group by ve_categoria 


    -- YA CON LOS DATOS HAREMOS EL AMARRE


          SELECT cat_id, Cat_nombre,
                COALESCE(TMPGASOLINA.CANTIDAD,0) GASOLINA
                COALESCE(TMPGASOIL.CANTIDAD,0) GASOIL
            FROM categoria
      LEFT JOIN TMPDESPACHOSGASOLINA TMPGASOLINA
              ON CATEGORIA.cat_id = TMPGASOLINA.ve_categoria
      LEFT JOIN TMPDESPACHOSGASOIL TMPGASOIL
              ON CATEGORIA.cat_id = TMPGASOIL.ve_categoria





a ver si esto sirve...
  • 0

#13 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 11:05 AM

Hola

Sólo algunas observaciones

Por que cambiar el nombre del campo CAT_ID por VE_CATEGORIA si es una FK, la regla dice que ambos deberian de tener el mismo nombre :)



Amigo mio, me has leido el pensamiento exactamente eso pensaba al leer el DDL



  • 0

#14 enecumene

enecumene

    Webmaster

  • Administrador
  • 7419 posts
  • LocationRepública Dominicana

Posted 26 October 2012 - 11:20 AM

Hola deCTod, muchas gracias por tomarte tu tiempo, en Firebird no se permite esta forma de "parametrizar":

GASOLINA = SUM(isNull(algo,0))


En el caso de que si no son FK tiene sus razones, de nuevo gracias por tu tiempo.

Poli, ¿Cuál sería la estructura de las tablas temporales?, fíjate que nunca se me hubiera ocurrido esa forma :D


  • 0

#15 William dFlota

William dFlota

    Member

  • Miembros
  • PipPip
  • 34 posts
  • LocationPerú

Posted 26 October 2012 - 11:32 AM

Hola deCTod, muchas gracias por tomarte tu tiempo, en Firebird no se permite esta forma de "parametrizar":

GASOLINA = SUM(isNull(algo,0))


En el caso de que si no son FK tiene sus razones, de nuevo gracias por tu tiempo.

Poli, ¿Cuál sería la estructura de las tablas temporales?, fíjate que nunca se me hubiera ocurrido esa forma :D



hola

Completamente de acuerdo contigo, sólo cambias lo siguiente

SUM(isNull(algo,0)) As Gasolina


Y como tengo entendido tampoco existe la función IsNull(), se lo quitas también

SUM(algo) As Gasolina


Bueno en todo caso si no es la solución que buscas, tiro la toalla jeje.


  • 0

#16 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 11:41 AM


Bueno en todo caso si no es la solución que buscas, tiro la toalla jeje.


no la tires amigo.. :) generalmente un problema se resuelve mejor desde varios enfoques y distintas propuestas... :D

Por cierto, veo que tienes bastante madera en lo que respecta al lenguaje sql.. Que motor de base de datos usas?

enecuneme: serían dos campos uno entero para el id de categoria que como  y el otro numérico para la sumatoria


  • 0

#17 enecumene

enecumene

    Webmaster

  • Administrador
  • 7419 posts
  • LocationRepública Dominicana

Posted 26 October 2012 - 11:43 AM

Muchas Gracias deCTod, en Firebird sería:

SUM(COALESCE(CAMPO,0)) AS GASOLINA


¡¡Poli!!, sos un genio mi estimado!!, hasta ahora me ha funcionado perfectamente, sólo me toca crear despachos con más categorías para ver la precisión del resultado, de nuevo, ¡¡muchas gracias a ambos!!.
  • 0

#18 William dFlota

William dFlota

    Member

  • Miembros
  • PipPip
  • 34 posts
  • LocationPerú

Posted 26 October 2012 - 11:47 AM



Bueno en todo caso si no es la solución que buscas, tiro la toalla jeje.


no la tires amigo.. :) generalmente un problema se resuelve mejor desde varios enfoques y distintas propuestas... :D

Por cierto, veo que tienes bastante madera en lo que respecta al lenguaje sql.. Que motor de base de datos usas?

enecuneme: serían dos campos uno entero para el id de categoria que como  y el otro numérico para la sumatoria


De ninguna manera tiraría la toalla, sólo lo dije a manera de broma :)

Bueno yo trabajo actualmente con SqlServer, Db2 y también e utilizado Interbase y un poco de Firebird, pero al final son lo mismo.

Además me gusta ayudar y recibir ayuda también por supuesto.

Así que si puedo ayudar en algo pues lo haré...



  • 0

#19 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 11:58 AM

Bueno yo trabajo actualmente con SqlServer, Db2 y también e utilizado Interbase y un poco de Firebird, pero al final son lo mismo.


Oye que bien¡¡¡¡¡¡¡ yo uso Sql Server 2000 y Db2 que está montado en un Iseries versión V5r2... me da mucho gusto saber que ya seremos más los que usamos db2 aquí en el foro.... saludos
  • 0

#20 poliburro

poliburro

    Advanced Member

  • Administrador
  • 4945 posts
  • LocationMéxico

Posted 26 October 2012 - 12:24 PM

Muchas Gracias deCTod, en Firebird sería:

SUM(COALESCE(CAMPO,0)) AS GASOLINA


¡¡Poli!!, sos un genio mi estimado!!, hasta ahora me ha funcionado perfectamente, sólo me toca crear despachos con más categorías para ver la precisión del resultado, de nuevo, ¡¡muchas gracias a ambos!!.


me alegra que lo hayas logrado echar a andar.... saludox
  • 0




IP.Board spam blocked by CleanTalk.