none
Union y tablas temporales en SQL compact server 2005

    Pregunta

  • Hola, tengo una duda para realizar una consulta SQL en la base de datos (Microsoft Server SQL compact 2005) que a continuación relato:

    Dispongo de dos tablas llamadas EntradaObra y SalidaObra que registran el materiales que entran y salen de las obras respectivamente. Ambas tablas disponen de un atributo que indica la obra, el artículo, la fecha del movimiento y la cantidad.
    EntradaObra (eo_ob_id, eo_art_cod, eo_fecha , eo_cant)
    SalidaObra (so_ob_id, so_art_cod, so_fecha , so_cant)

    Estoy intentando realizar una consulta en para calcular los materiales que hay en cada una de las obras (entradas menos las salidas), y es ahí donde me aparecen todos los problemas. He realizado esa consulta en el servidor (SQL Server 2005 Standard) sin ningún tipo de problema, del siguiente modo:


    select eo_ob_id as ex_ob_id, eo_art_cod as ex_art_cod, art_descrip as ex_art_descrip, sum(eo_cant) as ex_total
    from (select eo_ob_id, eo_art_cod, eo_cant from EntradaObra
    union all
    select so_ob_id, so_art_cod, -so_cant from SalidaObra) T, Articulo
    where eo_art_cod = art_cod
    group by eo_ob_id, eo_art_cod, art_descrip
    order by eo_ob_id, eo_art_cod;


    Proceso: Creo una unión de las entradas y las salidas, cambiando el signo de las cantidades de las salidas. El resultado es almacenado en una tabla temporal para su posterior procesado, sumando las cantidades de cada uno de los grupos creados (obras, artículos), Se añade los detalles desde otra tabla llamada Articulo que contiene información detallada de los artículos

    Obteniendo el siguiente resultado:
    tabla.png

    El problema aparece cuando intento realizar esa misma consulta en el PDA (Microsoft Server SQL compact 2005) ya que por lo que he probado, SQL compact no permite tablas temporales. Por esta razón no se como puedo calcular las existencias de materiales en las obras sin hacer uso de la union o de una tabla temporal.
    ¿me podéis ayudar con esto?

    Gracias de antemano.
    jueves, 23 de abril de 2009 14:30

Respuestas

Todas las respuestas

  • Hola danjes!

    Intenta con esta sentencia:

      select e.eo_ob_id as ex_ob_id, 
             e.eo_art_cod as ex_art_cod, 
             a.art_descrip as ex_art_descrip, 
             sum(e.eo_cant) - sum(s.so_cant) as ex_total
        from EntradaObra e
        join SalidaObra s on 
             e.eo_ob_id = s.so_ob_id
             and e.eo_art_cod = s.so_art_cod
        join Articulo a on
             e.eo_art_cod = a.art_cod
    group by e.eo_ob_id, e.eo_art_cod, a.art_descrip
    
    

    Anwar Karlier - MCTS SQL 2005
    • Editado Karlier jueves, 23 de abril de 2009 15:07 formato
    jueves, 23 de abril de 2009 15:06
  • Gracias por responder. Pero esa consulta no me vale, ya que se trata de un producto natural, no mostrandose las existencias de aquellos artículos que han tenido una entrada en la obra pero no una salida. Seguiré pensando a ver si se me ocurre algo.
    jueves, 23 de abril de 2009 16:08
  • Qué tal esta:

    select e.eo_ob_id as ex_ob_id, 
             e.eo_art_cod as ex_art_cod, 
             a.art_descrip as ex_art_descrip, 
             sum(e.eo_cant - s.so_cant) as ex_total
        from EntradaObra e
        join SalidaObra s on 
             e.eo_ob_id = s.so_ob_id
             and e.eo_art_cod = s.so_art_cod
        join Articulo a on
             e.eo_art_cod = a.art_cod
    group by e.eo_ob_id, e.eo_art_cod, a.art_descrip


    Perdón si no doy con el resultado que esperas. Quizá lo que si te puede servir es que utilices operadoes JOINs en lugar de tablas derivadas o compuestas seguidas de UNION ALL.

    Suerte, espero haberte dado al menos la idea.

    Saludos :)
    Anwar Karlier - MCTS SQL 2005
    jueves, 23 de abril de 2009 16:25
  • De nuevo gracias. No tienes que disculparte por nada, sobre todo teniendo tan poca información. Pero no veo como Joins puede servirme pues tiene un comportamiento muy distinto al de union

    Resultado de las dos operaciones

    Join (6 columnas):

    eo_ob_id, eo_art_cod, eo_cant, so_ob_id, so_art_cod, so_cant

    Union (3 columnas):

    Union de(eo_ob_id,so_ob_id), union de (eo_art_cod, so_art_cod), union de ( eo_cant,so_cant)

    PD: a punto de desistir y darlo por imposible.
    jueves, 23 de abril de 2009 18:11
  • Hola.

    No veo por qué no te funcionan las sentencias de union, están soportadas en SQL Server 2005 Compact Edition (http://technet.microsoft.com/en-us/library/ms174854.aspx). Luego, sin necesidad de guardar eso en una tabla temporal, puedes cruzarlo con la tabla Articulos. Seguramente ya lo hayas probado, pero por si acaso. Sería algo así, más o menos:

    Select tmp.*, A.*
    from 
      (
    	select eo_ob_id as ex_ob_id, eo_art_cod as ex_art_cod, art_descrip as ex_art_descrip, sum(eo_cant) as ex_total
    	from (select eo_ob_id, eo_art_cod, eo_cant from EntradaObra
    	union all
    	select so_ob_id, so_art_cod, -so_cant from SalidaObra) T, Articulo
    	where eo_art_cod = art_cod
    	group by eo_ob_id, eo_art_cod, art_descrip
      ) tmp inner join Articulos A on tmp.eo_art_cod = a.art_cod


    Alberto López Grande.

    jueves, 23 de abril de 2009 19:23
    Moderador
  • Gracias a los dos por las respuestas dadas.

    @Albert
    Creo que me he explicado mal, ya que no quería decir que en SQL compact server no se pueda usar la union ( que si se puede, como bien indicas), lo que creo es que no se puede usar una tabla temporal. Pues aunque esta consulta es correcta:


    select
     eo_ob_id, eo_art_cod, eo_cant from
     EntradaObra
    union
     all
    
    select
     so_ob_id, so_art_cod, -so_cant from
     SalidaObra
    


    No se como sumar la columna eo_cant que se obtiene de la consulta anterior sin una tabla temporal (llamada T en mi caso), como aquí indico:

    select
     eo_ob_id as
     ex_ob_id, eo_art_cod as
     ex_art_cod, sum
    (eo_cant) as
     ex_total
    from
     (select
     eo_ob_id, eo_art_cod, eo_cant from
     EntradaObra
    union
     all
    
    select
     so_ob_id, so_art_cod, -so_cant from
     SalidaObra) T
    group
     by
     eo_ob_id, eo_art_cod
    

    Nota: Para simplificar un poco la consulta voy a dejar a un lado los detalles del Articulo, con lo que sólo necesito 2 tablas y no tres.

    Dicha consulta es SQL Server 2005 es totalmente correcta pero en SQL compact Server obtengo el siguiente error:


    Error grave 0x80040E14, Error pequeño 25501
    > select
     eo_ob_id as
     ex_ob_id, eo_art_cod as
     ex_art_cod, sum
    (eo_cant) as
     ex_total
    from
     (select
     eo_ob_id, eo_art_cod, eo_cant from
     EntradaObra
    union
     all
    
    select
     so_ob_id, so_art_cod, -so_cant from
     SalidaObra) T
    group
     by
     eo_ob_id, eo_art_cod
    Error al analizar la consulta. [ Token line number = 2,Token line offset = 7,Token in error = select ]
    


    Daniel Villegas
    jueves, 23 de abril de 2009 21:41
  • Hola.

    Por lo que puedo observar, todo parece correcto. Intenta eliminar los alias de los campos y simplificar aún más la consulta, para ver si damos con el error. Primero trata de agrupar sólamente una de las dos partes de la union, por ejemplo:

    select eo_ob_id, sum(eo_cant) as ex_total from (select eo_ob_id, eo_cant from EntradaObra ) T group by eo_ob_id

    Si eso funciona, haz lo mismo con la otra:

    select eo_ob_id, sum(eo_cant) as ex_total from (select so_ob_id as eo_ob_id, -so_cant as eo_cant from SalidaObra) T group by eo_ob_id

    Luego con ambas:

    select eo_ob_id, sum(eo_cant) as ex_total from (select eo_ob_id, eo_cant from EntradaObra union 
    select so_ob_id as eo_ob_id, -so_cant as eo_cant from SalidaObra) T group by eo_ob_id

    Quedaría añadir una de las columnas. ¿Funcionan las tres o falla alguna?

    Alberto López Grande.

    viernes, 24 de abril de 2009 7:51
    Moderador
  • Agradezco vuestra ayuda, pero el problema no está en la consulta, sino en las limitaciones de SQL compact server 2005 . Para ver esta limitación voy ha exponer otra consulta con el mismo problema, pero aún más simplificada:


    select T.eo_ob_id
    from (
    	select eo_ob_id
    	from EntradaObra
    	union all
    	select so_ob_id
    	from SalidaObra
    )T

    Aunque la consulta roza lo absurdo, al estar haciendo una proyección del resultado de la tabla anterior (se obtiene el mismo resultado sin el select T.eo_ob_id), me vale como ejemplo para comprobar que el problema está en que no se puede almacenar el resultado de la unión en una tabla temporal T para su posterior procesado. Por esa razón aparece un error en el select de la linea 2.

    Aquí el error mostrado:

    Error grave 0x80040E14, Error pequeño 25501
    > select T.eo_ob_id
    from (
    	select eo_ob_id
    	from EntradaObra
    	union all
    	select so_ob_id
    	from SalidaObra
    )T
    Error al analizar la consulta. [ Token line number = 3,Token line offset = 2,Token in error = select ]
    

    La solución no está en los alis ni nada por el estilo, o eso creo. Lo que creo es que hay que transformar la consulta en otro tipo, ya sea una correlacionada o algo por el estilo. Siempre y cuando no haga uso de un tabla temporal. Ahí est´mi problema, que no se hacer eso.

    PD: La consulta es correcta en SQL server 2005
    viernes, 24 de abril de 2009 8:26
  • Hola.

    Discúlpame, por fin lo he pillado. Tienes SQL Server Compact Edition, pero ¿qué versión? Si no tienes la versión 3.5, entonces no puedes hacer consultas anidadas. Por un error (bueno, más bien por este link: http://www.microsoft.com/Sqlserver/2005/en/us/compact.aspx) he asumido que tenías la 3.5.

    Para tu caso entonces, puedes pasarte a la 3.5 o bien realizar un proceso que inserte primero en una tabla (que no te vale que sea una tabla temporal) y luego agrupar. Te dejo el link con la página (más fiable que donde miré primeramente) para obtener información y también la descarga de la 3.5: http://www.microsoft.com/Sqlserver/2008/en/us/compact.aspx.

    Alberto López Grande.
    viernes, 24 de abril de 2009 9:08
    Moderador
  • Gracias por la información. Lo tendré en cuenta para la próxima aplicación que haga. En este caso se quedará tal y como está.
    viernes, 24 de abril de 2009 9:22
  • Hay varias alternativas a utilizar tablas temporales,
    Algunas son
    1.CTE
    2. Variables Tipo Tabla
    3. Inserta temporalmente la data en una tabla #Nombre_Tabla y luego realizas el sum

    No se sin son soportadas por esta version de SQL , tendra que probar.

    • Propuesto como respuesta doryz jueves, 11 de abril de 2013 18:16
    viernes, 24 de abril de 2009 11:38