Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 18-10-2023
Avatar de Angel.Matilla
Angel.Matilla Angel.Matilla is offline
Miembro
 
Registrado: ene 2007
Posts: 1.350
Poder: 19
Angel.Matilla Va por buen camino
Uso de variables en un query

Hace ya tiempo me explicasteis como definir (RDB$SET_CONTEXT) y usar (RDB$GET_CONTEXT) variables en un query pero me ha llamdo la atención que esas variables definidas no puede usarse en las condiciones del query.

Por ejemplo: tengo definidas en un query estas dos variables.
Código SQL [-]
RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOS', ((SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                AND Proceso = A.CodPro AND (Partido > 1 OR Partido = (SELECT Codigo FROM Partidos 
                WHERE CodPrv = A.CodPrv AND Sigla = 'BLANCOS')) AND Mesa IN (SELECT Codigo FROM Mesas 
                WHERE CodPrv = A.CodPrv AND Municipio = A.Codigo))))

RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR', ((SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                AND Proceso = A.CodPro AND Partido = C.Partido AND Mesa IN (SELECT Codigo FROM Mesas 
                WHERE CodPrv = A.CodPrv AND Municipio = A.Codigo))))
y sin trato de hacer esto en un query:
Código SQL [-]
AND RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') >= 5 * RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOS') / 100
SQL Manager me da este error:
Cita:
Unsuccessful execution caused by a system error that precludes successful execution of subsequent statements.
Dynamic SQL Error.
Expression evaluation not supported.
Strings cannot be multiplied in dialect 3.
Entiendo que ese tipo de estructura es ilegal en Firebird o ¿lo estoy haciendo mal?
Responder Con Cita
  #2  
Antiguo 18-10-2023
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Prueba hacer un CAST de la variable...

"Strings cannot be multiplied"
implica que está tratando de multiplicar un string por un número.
Supongo que la variable siempre será de tipo string...
No se si se puede dar un tipo a la variable...

Código SQL [-]
AND RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') >= 5 * CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOS') AS DOUBLE PRECISION) / 100
Responder Con Cita
  #3  
Antiguo 18-10-2023
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Acabe de ver la documentación y dice <value> ::= A value of any type, as long as it's castable to a VARCHAR(255)
Por lo tanto la variable siempre es de tipo VARCHAR(255) y deberás hacer los CAST necesarios.

https://firebirdsql.org/refdocs/lang...t-context.html

Cita:
Available in: DSQL, ESQL, PSQL

Added in: 2.0

Description: Creates, sets or unsets a variable in one of the user-writable namespaces USER_SESSION and USER_TRANSACTION.

Result type: INTEGER

Syntax:

RDB$SET_CONTEXT ('<namespace>', '<varname>', <value> | NULL)

<namespace> ::= USER_SESSION | USER_TRANSACTION
<varname> ::= A case-sensitive string of max. 80 characters
***
<value> ::= A value of any type, as long as it's castable to a VARCHAR(255)
***
Responder Con Cita
  #4  
Antiguo 18-10-2023
Avatar de Angel.Matilla
Angel.Matilla Angel.Matilla is offline
Miembro
 
Registrado: ene 2007
Posts: 1.350
Poder: 19
Angel.Matilla Va por buen camino
Cita:
Empezado por duilioisola Ver Mensaje
Acabe de ver la documentación y dice <value> ::= A value of any type, as long as it's castable to a VARCHAR(255)
Por lo tanto la variable siempre es de tipo VARCHAR(255) y deberás hacer los CAST necesarios.
Pues tienes razón. Como siempre, me tiro de cabeza a la piscina sin mirar si hay antes agua. Muchas gracias.
Responder Con Cita
  #5  
Antiguo 19-10-2023
Avatar de Angel.Matilla
Angel.Matilla Angel.Matilla is offline
Miembro
 
Registrado: ene 2007
Posts: 1.350
Poder: 19
Angel.Matilla Va por buen camino
Sigo estrellándome una y otra vez. A ver si me ayudáis a ver que está mal porque yo soy incapaz. Tengo este query:
Código SQL [-]
SELECT DISTINCT A.Codigo, A.Nombre, CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS INTEGER) Votos, 
       COALESCE(C.Electos, 0) Electos, CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS INTEGER) Total,
       RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR', (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                       AND Proceso = B.Proceso 
                       AND Partido = A.Codigo
                       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217))),
       RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT', (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                       AND Proceso = B.Proceso 
                       AND (Partido > 0 OR Partido = (SELECT Codigo FROM Partidos WHERE CodPrv = A.CodPrv AND Sigla = 'BLANCOS'))
                       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217)))
  FROM Partidos A, Resultados B
  LEFT JOIN NumElectos C ON B.CodPrv = C.CodPrv AND B.Proceso = C.Proceso AND C.Tipo = 'M' AND C.Circunscripcion = 1217 AND B.Partido = C.Partido
 WHERE A.CodPrv = '13' AND A.Codigo > 0
   AND B.Proceso = 42 AND A.CodPrv = B.CodPrv AND B.Partido = A.Codigo
   AND B.Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217)
 ORDER BY Votos DESC, Electos DESC, Nombre
Así, tal cual, da este resultado:

Primero que nada que no entiendo por qué aparece tres veces el primer registro si todos los datos son iguales; eso ya me ha dejado perplejo. Además, y de acuerdo con el query, las tres últimas filas están mal ordenadas.

Si al query le añado la sintaxis que me sugirió duilioisola, así:
Código SQL [-]
SELECT DISTINCT A.Codigo, A.Nombre, CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS INTEGER) Votos, 
       COALESCE(C.Electos, 0) Electos, CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS INTEGER) Total,
       RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR', (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                       AND Proceso = B.Proceso 
                       AND Partido = A.Codigo
                       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217))),
       RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT', (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                       AND Proceso = B.Proceso 
                       AND (Partido > 0 OR Partido = (SELECT Codigo FROM Partidos WHERE CodPrv = A.CodPrv AND Sigla = 'BLANCOS'))
                       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217)))
  FROM Partidos A, Resultados B
  LEFT JOIN NumElectos C ON B.CodPrv = C.CodPrv AND B.Proceso = C.Proceso AND C.Tipo = 'M' AND C.Circunscripcion = 1217 
            AND B.Partido = C.Partido
 WHERE A.CodPrv = '13' AND A.Codigo > 0
   AND B.Proceso = 42 AND A.CodPrv = B.CodPrv AND B.Partido = A.Codigo
   AND B.Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217)
   AND CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS DOUBLE PRECISION) >= 5 * CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS DOUBLE PRECISION) / 100
 ORDER BY Votos DESC, Electos DESC, Nombre
Entonces no me devuelve nada y lo que tendría que mostrar son aquellos registros en los que los votos sean iguales o mayores que el 5% del total (796); es decir: las tres últimas filas no deberíanb mostrarse.
Responder Con Cita
  #6  
Antiguo 19-10-2023
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
1ra Pregunta - Por que se triplica el primer registro.

Seguramente porque el JOIN que utilizas lo triplica
Por ejemplo si hubiera 1 "Partidos" con 3 "NumElectos" que cumplan la condición del join.
También puede ser porque hay 1 "Partidos" con 3 "Resultados" que cumplen la condición B.Partido = C.Partido.

Para debugar este problema debes hacer un SELECT * y ver qué columnas son las diferentes.
Por ejemplo:
Código SQL [-]
SELECT *
  FROM Partidos A, Resultados B
  LEFT JOIN NumElectos C ON B.CodPrv = C.CodPrv AND B.Proceso = C.Proceso AND C.Tipo = 'M' AND C.Circunscripcion = 1217 AND B.Partido = C.Partido
 WHERE 
   A.CodPrv = '13' AND A.Codigo > 0
   AND B.Proceso = 42 AND A.CodPrv = B.CodPrv AND B.Partido = A.Codigo
   AND B.Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217)
 ORDER BY /*Votos DESC,*/ Electos DESC, Nombre
Te saldrán todas las columnas de cada tabla. Serán todas iguales excepto las de la tabla que se repite.
Solución: deberás corregir...


2da Pregunta: El orden es incorrecto.

Veo que hay campos para los que no utilizas ALIAS. Si se repiten en varias tablas puede estar ordenando por el que no quieres.
Corrige el ORDER BY
Para el campo Electos debes utilizar la función COALESCE porque de lo contrario los nulos estarán al principio (o al final, no recuerod).
Entiendo que nombre es de la tabla "Partidos". Puede que haya otro campo Nombre en otra de las tablas.
Votos no se decirte, porque es una función. Yo utilizaría la función completa con el CAST a integer para evitar que lo ordene como string ('1', '10', '11', ..., '2', '20', ...)
Código SQL [-]
 ORDER BY CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS INTEGER) DESC, COALESCE(C.Electos, 0) DESC, A.Nombre


3ra Pregunta: No sale nada si agregas la condición al WHERE.

Lo más sencillo es agregarlo como dato para comprobar que lo que sale es lo que supones que debe salir... podría haber nulos o los CAST están convirtiéndo cosas raras, etc.
Veo que se trata de enteros, por lo que quizás el CAST deba ser a INTEGER.

Código SQL [-]
SELECT DISTINCT A.Codigo, A.Nombre, CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS INTEGER) Votos, 
       COALESCE(C.Electos, 0) Electos, CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS INTEGER) Total,
       RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR', (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                       AND Proceso = B.Proceso 
                       AND Partido = A.Codigo
                       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217))),
       RDB$SET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT', (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv 
                       AND Proceso = B.Proceso 
                       AND (Partido > 0 OR Partido = (SELECT Codigo FROM Partidos WHERE CodPrv = A.CodPrv AND Sigla = 'BLANCOS'))
                       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217))),
       -- Campos como Float
       CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS DOUBLE PRECISION),  CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS DOUBLE PRECISION), 
       -- Campos como Enteros
       CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS INTEGER),  CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS INTEGER),
       -- Resultado la la formula utilizada
       (5 * CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS DOUBLE PRECISION) / 100)
  FROM Partidos A, Resultados B
  LEFT JOIN NumElectos C ON B.CodPrv = C.CodPrv AND B.Proceso = C.Proceso AND C.Tipo = 'M' AND C.Circunscripcion = 1217 
            AND B.Partido = C.Partido
 WHERE A.CodPrv = '13' AND A.Codigo > 0
   AND B.Proceso = 42 AND A.CodPrv = B.CodPrv AND B.Partido = A.Codigo
   AND B.Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = 1217)
   -- AND CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSPAR') AS DOUBLE PRECISION) >= 5 * CAST(RDB$GET_CONTEXT('USER_TRANSACTION', 'VOTOSTOT') AS DOUBLE PRECISION) / 100
 ORDER BY Votos DESC, Electos DESC, Nombre
Responder Con Cita
  #7  
Antiguo 19-10-2023
Avatar de duilioisola
[duilioisola] duilioisola is offline
Miembro Premium
 
Registrado: ago 2007
Ubicación: Barcelona, España
Posts: 1.734
Poder: 20
duilioisola Es un diamante en brutoduilioisola Es un diamante en brutoduilioisola Es un diamante en bruto
Sugerencia:

No mezcles las formas de unir tablas.
Yo utilizaría solo JOINS porque creo que se lee mejor.
Cuando mezclas formas no se entiende a la primera la intención de lo que deseas hacer.

Normalmente en la parte ON (...) se utilizan los campos de la PK de la tabla "padre", aunque a veces no es lo que se desea.

Por otro lado quita del JOIN las partes constantes y muévelas a la parte WHERE. Por ejemplo para el JOIN que haces con NUMELECTOS.
La única excepción que haría es si se trata de optimizar y por lo que sea el motor de base de datos entiende mejor una forma que la otra.

Ejemplo:
Código SQL [-]
select *
from partidos a
/*LEFT?*/ join resultados b on a.codprv = b.codprv and b.partido = a.codigo
left join numelectos c on b.codprv = c.codprv and b.proceso = c.proceso and b.partido = c.partido
where
-- Filtros de PARTIDO
a.codprv = '13' and
a.codigo > 0 and
-- Filtros de Resultados
b.proceso = 42 and
b.mesa in (select codigo
           from mesas
           where
           codprv = a.codprv and
           municipio = 1217) and
-- Filtros de NUMELECTOS
c.tipo = 'M' and
c.circunscripcion = 1217
order by /*Votos DESC,*/ coalesce(c.electos, 0) desc, a.nombre
Responder Con Cita
  #8  
Antiguo 20-10-2023
Avatar de Angel.Matilla
Angel.Matilla Angel.Matilla is offline
Miembro
 
Registrado: ene 2007
Posts: 1.350
Poder: 19
Angel.Matilla Va por buen camino
Muchas gracias por tus respuestas. Probaré los cambios que me sugieres.
Cita:
Empezado por duilioisola Ver Mensaje
Yo utilizaría la función completa con el CAST a integer para evitar que lo ordene como string ('1', '10', '11', ..., '2', '20', ...)
En este caso no me interesa que se clasifique como "palabra".

Última edición por Angel.Matilla fecha: 20-10-2023 a las 09:44:54.
Responder Con Cita
  #9  
Antiguo 20-10-2023
Avatar de Angel.Matilla
Angel.Matilla Angel.Matilla is offline
Miembro
 
Registrado: ene 2007
Posts: 1.350
Poder: 19
Angel.Matilla Va por buen camino
Cita:
Empezado por duilioisola Ver Mensaje
3ra Pregunta: No sale nada si agregas la condición al WHERE.

Lo más sencillo es agregarlo como dato para comprobar que lo que sale es lo que supones que debe salir... podría haber nulos o los CAST están convirtiéndo cosas raras, etc.
Curiosamente con este query que me planteas en esa 3ª respuesta la ordenación la hace alfabéticamente:

y eso a pesar de que el Nombre es el último campo de ordenación y el primero es la columna Votos que es un entero. Cada vez lo entiendo menos.
Responder Con Cita
  #10  
Antiguo 20-10-2023
cloayza cloayza is offline
Miembro
 
Registrado: may 2003
Ubicación: San Pedro de la Paz, Chile
Posts: 913
Poder: 22
cloayza Tiene un aura espectacularcloayza Tiene un aura espectacular
Creo recordar que en alguna oportunidad me sucedió algo parecido...Intenta utilizar los indices de las columnas para realizar el ordenamiento...

Código SQL [-]
--Reemplazar
--ORDER BY Votos DESC, Electos DESC, Nombre

--Por esto...
ORDER BY 3 DESC, 4 DESC, 2

Saludos cordiales
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Variables en un query Angel.Matilla Firebird e Interbase 3 24-06-2022 11:35:05
Realizar un Update en delphi con un query concondicion desde otro query!!! rotsen26 SQL 9 09-03-2013 22:17:47
??enviar variables de consulta de un query a reporte lazreport?? jasmad Lazarus, FreePascal, Kylix, etc. 2 27-10-2011 20:22:22
Variables por Referencia y Query Raynel Tablas planas 1 25-02-2008 10:51:24
variables variables (manual php) salvica PHP 0 25-09-2005 16:44:52


La franja horaria es GMT +2. Ahora son las 12:46:03.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi