Ir al contenido


Foto

problema en la visibilidad de un campo


  • Por favor identifícate para responder
12 respuestas en este tema

#1 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 29 mayo 2015 - 11:50

Hace poco tuve que cambiar la forma en que registro el stock y se me ocurrió separarlo en una tabla llamada stock (un nombre muy  original). El asunto es que para poder ordenar y discriminar los campos visualizados necesito relacionarlo a la tabla de artículos.

 

la sentencia toma la forma:


sql
  1. SELECT ref_art, denom, SUM(stock.cantidad)
  2. FROM stock
  3. INNER JOIN articulo ON (aticulo.id_art = stock.ref_art)
  4. GROUP BY ref_art, denom

En este caso los valores son devueltos fácilmente, excepto por que es imposible aplicar una cláusula where debido a la existencia de la cláusula group by, y mediante la cláusual having no es posible mostrar el campo obtenido por sum().


sql
  1. SELECT ref_art, excrit, SUM(stock.cantidad) AS total
  2. FROM stock
  3. INNER JOIN articulo ON (articulo.id_art = stock.ref_art)
  4. GROUP BY ref_art, excrit
  5. HAVING (total > excrit)
  6.  
  7. /* podría escribirlo así */
  8. SELECT articulo.ref_art, articulo.excrit, SUM(stock.cantidad) AS total
  9. FROM stock
  10. INNER JOIN articulo ON (articulo.id_art = stock.ref_art)
  11. GROUP BY ref_art, excrit
  12. HAVING (total > excrit)

En este segundo caso, el procesador no reconoce el campo total. Probé nombrarlo con comillas y tampoco funcionó.

Estoy usando Firbird 2.5.2.

 

Solucioné el problema con otra sentencia sin usar el join (incluso con resultados mucho más satisfactorios), pero pregunto: ¿por qué no se puede ver el campo total?. El procesador lo ignora.

 

Saludos

 


  • 0

#2 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 29 mayo 2015 - 01:08

Saludos.

 

Tal vez si pones el nombre de la tabla o alias delante de cada columna para que el motor sepa que debe hacer.


  • 0

#3 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 29 mayo 2015 - 01:25

Saludos.

 

Tal vez si pones el nombre de la tabla o alias delante de cada columna para que el motor sepa que debe hacer.

 

Es que precisamente un alias lo que el motor no puede ver. Ya que es un campo resultado de una función SUM().

 

Saludos y gracias por la idea Rolphy, pero ya probé anteponiendo los nombres.


  • 0

#4 Nikolas

Nikolas

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 604 mensajes
  • LocationMar del Plata / Bs As / Argentina

Escrito 29 mayo 2015 - 07:29

Esto me  funciona, no se si te ayuda:

 

 

select IDdistribuidor,ArtProveedor,A.color,sum(bultos * unidades) as SUMA

from PEDIDOSDETALLE PD
join PEDIDOSCABECERA PC

on pc.numero = pd.numero join articulos A on pd.articulo = A.codigo

where
pc.fecha between :Pf1 AND :Pf2 and IDdISTRIBUIdor = :Pid

group by artproveedor,iddistribuidor,A.color
order by SUMA desc


  • 1

#5 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 30 mayo 2015 - 11:49

Gracias por tu ayuda Nikolas. Pero te comento que solucioné el problema utilizando otra técnica, o sea dando vuelta a ese SELECT.

El tema en cuestión es la visibilidad, probá hacer algo parecido y verás que es imposible nombrar a un alias de ese tipo.

Respecto de tu consulta, es útil pero no en el caso en que trato de utilizar en el sistema. Ya que es para ver solo el stock que tiene características puntuales como existencias críticas, existencias suficientes, nulas, etc.

 

Gracias de nuevo, saludos

(b)


  • 0

#6 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 01 junio 2015 - 02:19

Buenas,

 

No lo he probado, pero lo siguiente debería de funcionarte (tampoco sé que tan bueno será el rendimiento de la consulta)


sql
  1. SELECT ref_art, excrit, SUM(stock.cantidad) AS total
  2. FROM stock
  3. INNER JOIN articulo ON (articulo.id_art = stock.ref_art)
  4. GROUP BY ref_art, excrit
  5. HAVING (SUM(stock.cantidad) > excrit)

Por cierto, la recomendación de Rolphy es buena, que aunque no te permita acceder al campo agregado, da más claridad a la sentencia

 

Salut!


  • 0

#7 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 01 junio 2015 - 02:20

Muchas gracias Cadetil.

 

Estaba por escribir la sentencia que utilizo, pero me es imposible ahora traducirla en términos de lo que escribí al inicio. Por lo que la dejo para otro día.

Aún así, Cadetil, al hacer uso de la función SUM de nuevo una vez más no utilizamos el alias. :undecided:

Esa solución ya se me había ocurrido, pero imagínate que tengas que escribir cuatro o cinco funciones y luego reescribirlas debido a la incapacidad de nombrarlas con el alias. No sé como se comportará el procesador, si vuelve a producir código para la función o reutiliza el resultado (me tiro por lo primero). COn esto, lo que quiero decir es que esa incapacidad de nombrar a ese alias es lo que me motivó para iniciar el hilo, para saber si alguien sabia el porque. Me imagino que al nombrar más de una vez a una función, la consulta puede volverse ineficiente, ya que SUM recorre toda el conjunto de filas.

 

Quizá lo deba mover a desafíos. Ya que ya no representa un problema de conseguir los valores sino que una sentencia haga lo que uno pretende.

 

Te comento que a veces me encierro con un problema po cuestiones de desafío y olvido la razón por la cual estaba buscando la solución. :tongue:

 

Saludos.


  • 0

#8 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 02 junio 2015 - 04:22

Al final la sentencia queda como sigue:


sql
  1. SELECT * FROM
  2. (SELECT articulo.*, (SELECT SUM(cantidad) FROM stock WHERE stock.ref_art = articulo.id_art) AS "total"
  3. FROM articulo WHERE "total" < articulo.excrit ORDER BY articulo.denom

select * from el conjunto que se especifica luego, esto reune toda la información devuelta en un solo conjunto.

select articulo.* lo hace from la tabla articulo, agregando como campo un nuevo select sum(cantidad) from la tabla stock, siempre que coincida su campol ref_art con el campo id_art del mismo select (select articulo.*) y lo llama "total".

la cláusula where trabaja en el segundo nivel del select, por lo que puede hacer uso de todo articulo.* y de la variable "total" (que es el resultado de la función sum aplicada a un conjunto selecto de la tabla stock) y coincide con el valor id_art del select articulo.*. Esto es un join y un having implícitos.

Al final puedo hacer uso libremente de cualquier campo del select.

 

(Solo como comentario)

Esta es la versión corta, ya que en realidad no utilizo, una tabla stock, cambié la mecánica de recuento de las existencias. En realidad cambié todo. Y gracias al select de Nikolas que incluyó una tabla PEDIDOS, se me encendió la lamparita para agregar aun más funcionalidad al mecanismo de stock. (y)

 

Sobre la visibilidad, que era el tema en cuestión sería bueno contactar con algún especialista en firebird, ya que hay algo raro en esto, si lo analizan bien, se darán cuenta que es un problema en ciertos casos. Lamentablemente, yo estoy aprendiendo sobre la marcha (dadas las circunstancias) y aun no leí ningún libro, y creo que es hora de hacerlo. Me sorprende algunas cosas que el procesador tiene "ocultas".

 

Saludos.


  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 02 junio 2015 - 08:10

 sería bueno contactar con algún especialista en firebird

 

Los tenemos amigo: los compañeros Rolphy Reyes, Wilson, Sergio y Marc ha demostrado ser de las personas que más saben de Firebird por este foro.

 

La otra posibilidad es contactar a la gente de un Grupo de Yahoo! en español. También hay otro en inglés, creo recordar que este es el oficial. Y de última consideraría contactar al propio equipo de Firebird. En la página oficial están los enlaces para contactarse.

Lo recuerdo de aquella vez que me puse en contacto con Ernesto Cullen, encargado de llevar la traducción de la documentación al español. Al día de hoy no se si el sigue al cargo o es otra persona.

 

Saludos,


  • 0

#10 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 02 junio 2015 - 10:08

Los tenemos amigo: los compañeros Rolphy Reyes, Wilson, Sergio y Marc ha demostrado ser de las personas que más saben de Firebird por este foro.

 

 

Gracias Delphius por tus palabras, en realidad no soy un experto, pero con alguna experiencia que tengo con Firebird puedo decirte que no hay tal redundancia, el alias es solo por ponerle un nombre a la columna de salida,a tal punto que puedes omitirlo, si no lo colocas pues el le asigna un nombre, lo que verdaderamente importa es la expresión. En este orden de ideas concuerdo 100% con la consulta de Cadetill, el optimizador está diseñado justo para eso. La clausula HAVING actúa solo como una  restricción o filtro sobre lo planteado en la primera parte de la consulta. En tu caso la lógica indicaría que primero ejecuta la primera parte de la consulta, luego el motor revisa cuales registros de los ya obtenidos cumplen con la condición de HAVING sin necesidad de volver a ejecutar la primera parte de la consulta.

 

Saludos.

 

PD : A continuación una cita del libro:The Firebird Book: A Reference for Database Developers.

He resaltado en rojo la parte que nos interesa.

 

 

HAVING <Grouping-Column Predicate>

 

The optional HAVING clause may be used in conjunction with a grouping specification
to include or exclude rows or groups, similar to the way the WHERE clause limits row
sets. Often, in a grouping query, a HAVING clause can replace the WHERE clause.
 
However, because HAVING operates on the intermediate set created as input to the
GROUP BY specification, it may be more economical to prefer a WHERE condition to
limit rows and a HAVING condition to limit groups.
 
The previous example is modified by a HAVING clause, to return just the
PRODUCT_TYPE that has been sold in quantities greater than 100:
 
SELECT PRODUCT_TYPE, SUM(NUMBER_SOLD) AS SUM_SALES
FROM TABLEA
WHERE SERIAL_NO BETWEEN 'A' AND 'K'
AND PRODUCT_TYPE = 'WIDGETS'
GROUP BY PRODUCT_TYPE
HAVING SUM(NUMBER_SOLD) > 100;

  • 2

#11 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 02 junio 2015 - 12:35

Oooppps... perdón. :embarrassed:

No quise ofender a nadie. Sé que hay gente que domina Firebird en DelphiAccess. Sergio, Wilson, Rolhy, Marc más de una vez me han dado más de una mano.

Pero no me refería a eso. Sino a esa gente que está involucradísima en el mismo desarrollo de Firebird y conoce hasta el más sucio bicho que tiene el producto.

Puestoque hay errores (bugs, me refiero a eso) que más experiencia que tengamos y libros que hayamos leído no las sabremos, pues no están documentadas y es muy probable que no hayamos andado por ese lugar.

 

Saludos

 

Fue una "metida de pata" expresarme sin precisión. (b)


  • 0

#12 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 02 junio 2015 - 12:43

Gracias Delphius por tus palabras, en realidad no soy un experto, pero con alguna experiencia que tengo con Firebird puedo decirte que no hay tal redundancia, el alias es solo por ponerle un nombre a la columna de salida,a tal punto que puedes omitirlo, si no lo colocas pues el le asigna un nombre, lo que verdaderamente importa es la expresión. En este orden de ideas concuerdo 100% con la consulta de Cadetill, el optimizador está diseñado justo para eso. La clausula HAVING actúa solo como una  restricción o filtro sobre lo planteado en la primera parte de la consulta. En tu caso la lógica indicaría que primero ejecuta la primera parte de la consulta, luego el motor revisa cuales registros de los ya obtenidos cumplen con la condición de HAVING sin necesidad de volver a ejecutar la primera parte de la consulta.
 
Saludos.
 
PD : A continuación una cita del libro:The Firebird Book: A Reference for Database Developers.
He resaltado en rojo la parte que nos interesa.
 
(no pude citar, tuve que copiar y pegar)


Entonces, Wilson, dices que no importa cuantas veces escribamos una función, ¿el procesador hará un buen trabajo? Es que de ahí partió mi problema, ya que al principio me había planteado usar dos veces el sum, pero lo creí ineficiente y además me gustó el desafío.
 
Saludos.
(y)

Editado por egostar, 02 junio 2015 - 01:27 .
Agregue etiqueta de citar.

  • 0

#13 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 02 junio 2015 - 01:15

 

Entonces, Wilson, dices que no importa cuantas veces escribamos una función, ¿el procesador hará un buen trabajo? 

 

Por supuesto que hará bien el trabajo, al menos en el contexto del HAVING.  SQLServer, Oracle, Postgresql lo hacen del mismo modo.

 

Saludo.


  • 1




IP.Board spam blocked by CleanTalk.