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 28-01-2020
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
Unhappy Pivote: Sigo sin entenderlo...

Lo siento. Por más vueltas que le doy no acabo de entender bien como hacer este tipo de querys. Creo que he visto todos los hilos en los que se trata este tema; estuve viendo el código que puso fjcg02 en Trasnformadas, crosstab, pivot, referencias cruzadas ...

(Un apunte: El código del ejemplo da un error -607 Malformed string al ejecutarlo con SQL Manager, y no he sido capaz de ver dónde está)

A partir de esta tabla:


quiero montar un query; los campos son INTEGER. En principìo había pensado en una salida parecida a esta:

Para esta salida uso este query:
Código SQL [-]
WITH Pivote AS (SELECT Codigo, Votos2, Total FROM SYSDBA122540 WHERE Total > 0) 
SELECT A.Nombre, 
       CAST(100 * MAX(C.VOTOS2) AS DECIMAL(10 ,2))/CAST(MAX(C.Total) AS DECIMAL(10 ,2)) PorcC, 
       CAST(100 * MAX(D.VOTOS2) AS DECIMAL(10 ,2))/CAST(MAX(D.Total) AS DECIMAL(10 ,2)) PorcD, 
       CAST(100 * MAX(E.VOTOS2) AS DECIMAL(10 ,2))/CAST(MAX(E.Total) AS DECIMAL(10 ,2)) PorcE, 
       CAST(100 * MAX(F.VOTOS2) AS DECIMAL(10 ,2))/CAST(MAX(F.Total) AS DECIMAL(10 ,2)) PorcF 
  FROM Proceso A, SYSDBA122540 B 
  LEFT JOIN Pivote C ON B.Codigo = C.Codigo AND C.Codigo IN (25, 26, 35, 24) 
  LEFT JOIN Pivote D ON B.Codigo = D.Codigo AND D.Codigo IN (29, 30, 36, 28) 
  LEFT JOIN Pivote E ON B.Codigo = E.Codigo AND E.Codigo IN (33, 34, 37, 32) 
  LEFT JOIN Pivote F ON B.Codigo = F.Codigo AND F.Codigo IN (40, 38, 42, 39) 
 WHERE A.Codigo = B.Proceso GROUP BY A.Nombre ORDER BY Nombre
Pero probablemente me sea más útil para lo que quiero otra en que los nombres de las columnas sean cada uno de los tipos (municipales, autonómicas, etc.) y en cada fila esté cada uno de lso resultados. Algo así:
Código:
Orden    Municipales   Autonómicas   Generales   Europeas
1           40,0009    39,2431       38,5656     49,0767
2           45,9111    46,9671       43,5847     51,1198   
3           37,0923    37,0738       23,5756     38,8671
4           35,5026    28,5302       21,4285     28,6433
y por más vueltas que doy no sé como montarlo para que me genere esta última salida. De verdad que no acabo de entender cómo montar estos querys.

Última edición por Angel.Matilla fecha: 28-01-2020 a las 18:33:10.
Responder Con Cita
  #2  
Antiguo 28-01-2020
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Sigues sin entender porque no haces caso. Te he dicho que pivote con JOINS no es la manera. Hay te puse un link a un tutorial, si lo miraste?.

Reitero: Sin ayuda del motor, hacer esto REQUIERE HACER PASOS "manuales". TIENES que usar CASE para "filtrar" los datos de columnas junto con GROUP BY.

Te paso otro link que muestra los pasos:

https://modern-sql.com/use-case/pivot

(Ahi usan FILTER pero es lo mismo con CASE)
__________________
El malabarista.
Responder Con Cita
  #3  
Antiguo 28-01-2020
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 mamcx Ver Mensaje
Sigues sin entender porque no haces caso. Te he dicho que pivote con JOINS no es la manera. Hay te puse un link a un tutorial, si lo miraste?.

Reitero: Sin ayuda del motor, hacer esto REQUIERE HACER PASOS "manuales". TIENES que usar CASE para "filtrar" los datos de columnas junto con GROUP BY.

Te paso otro link que muestra los pasos:

https://modern-sql.com/use-case/pivot

(Ahi usan FILTER pero es lo mismo con CASE)
Gracias por la respuesta. Mañana la miraré con calma donde tengo el proyecto. No obstante el uso del JOIN lo justifica porque puede no haber datos en todos los códigos; sólo por eso. Y, en cualquier caso, tengo que montar el query de forma manual porque el usuario puede decidir cuantos resultados recupera; yo estoy poniendo cuatro porque eso es lo que uso para las pruebas, pero puede querer más o menos.
Responder Con Cita
  #4  
Antiguo 29-01-2020
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
Lo siento. No soy capaz de encontrar la solución. Ante todo gracias a mamcx por los enlaces que ha puesto; me han aclarado algunas cosas, pero el problema es que todos los ejemplos que vienen son con funciones que agrupan (SUM, COUNT, etc.) y por lo tanto hace falta GROUP BY pero yo necesito las filas individuales. Tengo que pasar de esta tabla:

a esta otra:

entendiendo que la primera fila (3, 4, etc.) serían los nombres de las columnas. Me da lo mismo hacerlo con un pivote o como sugiere mamcx con CASE, pero no se me ocurre absolutamente ninguna forma. Lo más próximo que he logrado con:
Código SQL [-]
SELECT CASE WHEN A.Proceso = 3 THEN A.Votos2 END Europeas,
       CASE WHEN A.Proceso = 4 THEN A.Votos2 END Generales,
       CASE WHEN A.Proceso = 5 THEN A.Votos2 END Autonomicas,
       CASE WHEN A.Proceso = 6 THEN A.Votos2 END Municipales
  FROM SYSDBA122540 A
es esto:

que evidentemente no es lo que busco.
Responder Con Cita
  #5  
Antiguo 29-01-2020
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
Estimado Angel.Matilla, me intereso tu problema y creo que hay una opción, por supuesto no será la única ni la mejor, pero es un comienzo.

Esta solución consta de dos partes:
1) Procedimiento almacenado: Que genera un correlativo dentro de cada "PROCESO"
Proceso Fila
3 1
3 2
3 3
3 4
4 1
4 2
4 3
...

Código SQL [-]
create procedure SP_PROCESO_FILAS
  returns (
    proceso integer,
    fila integer,
    codigo integer,
    votos2 integer,
    total integer)
as
declare variable OldProc integer;
begin
  
  OldProc=-1;
  fila=0;
  for select proceso, codigo, votos2, total
      from votos
      into : proceso,
           :codigo,
           :votos2,
           :total
  do
  begin
        if (OldProc<>proceso) then
        begin
            fila=0;
            OldProc=proceso;
        end

        fila=fila+1;
        suspend;
  end
end

2) Consulta que utiliza el procedimiento almacenado y genera la vista de los datos según el formato requerido.
Código SQL [-]
/*
Esta consulta genera los procesos en forma de columnas
utiliza sp_procesos_filas
*/
select a.fila,
       sum(iif(A.Proceso = 3, A.Votos2,0)) Europeas,
       sum(iif(A.Proceso = 4, A.Votos2,0)) Generales,
       sum(iif(A.Proceso = 5, A.Votos2,0)) Autonomicas,
       sum(iif(A.Proceso = 6, A.Votos2,0)) Municipales
from SP_PROCESO_FILAS a
group by a.fila


Espero te sirva, saludos cordiales

Última edición por cloayza fecha: 29-01-2020 a las 15:27:56.
Responder Con Cita
  #6  
Antiguo 29-01-2020
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 cloayza Ver Mensaje
Estimado Angel.Matilla, me intereso tu problema y creo que hay una opción, por supuesto no será la única ni la mejor, pero es un comienzo.

Esta solución consta de dos partes:
cloayza: ¡¡¡CHAPEAU!!! Es exactamente lo que me hace falta. Tendré que pulirlo porque la tabla de la que saco los datos se crea en tiempo de ejecución pero efectivamente es la saldia que me hacía falta. Te invito a unas
Responder Con Cita
  #7  
Antiguo 29-01-2020
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 cloayza Ver Mensaje
Estimado Angel.Matilla, me intereso tu problema y creo que hay una opción, por supuesto no será la única ni la mejor, pero es un comienzo.
Me está ocurriendo una cosa curiosísima. Si ejecuto el código para crear el procedimiento desde SQL Manager no da ningún problema; se crea y me deja hacer el select posterior sin problema alguna. Si lo creo por código desde el proyecto me da un error de sintaxis en la línea into :proceso,:
Cita:
Dynamic SQL Error
SQL error code = -104
Token unknown - line 15, column 10
?
No lo entiendo ¿Cuál puede ser la razón?

Última edición por Angel.Matilla fecha: 29-01-2020 a las 19:38:05.
Responder Con Cita
  #8  
Antiguo 29-01-2020
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.040
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cambia el nombre de esa variable, ponle por ejemplo vproceso, es que tienes un campo que se llama igual.
Responder Con Cita
  #9  
Antiguo 29-01-2020
Avatar de fjcg02
[fjcg02] fjcg02 is offline
Miembro Premium
 
Registrado: dic 2003
Ubicación: Zamudio
Posts: 1.410
Poder: 22
fjcg02 Va camino a la fama
Cita:
Empezado por Angel.Matilla Ver Mensaje
Lo siento. No soy capaz de encontrar la solución. Ante todo gracias a mamcx por los enlaces que ha puesto; me han aclarado algunas cosas, pero el problema es que todos los ejemplos que vienen son con funciones que agrupan (SUM, COUNT, etc.) y por lo tanto hace falta GROUP BY pero yo necesito las filas individuales. Tengo que pasar de esta tabla:

a esta otra:

entendiendo que la primera fila (3, 4, etc.) serían los nombres de las columnas. Me da lo mismo hacerlo con un pivote o como sugiere mamcx con CASE, pero no se me ocurre absolutamente ninguna forma. Lo más próximo que he logrado con:
Código SQL [-]
SELECT CASE WHEN A.Proceso = 3 THEN A.Votos2 END Europeas,
       CASE WHEN A.Proceso = 4 THEN A.Votos2 END Generales,
       CASE WHEN A.Proceso = 5 THEN A.Votos2 END Autonomicas,
       CASE WHEN A.Proceso = 6 THEN A.Votos2 END Municipales
  FROM SYSDBA122540 A
es esto:

que evidentemente no es lo que busco.
Hola, una cosa solamente... qué criterio utilizas para agrupar los valores por filas? No hay un orden determinado, podrían salirte ordenados los registros de cualquier manera dependiendo de lo que al motor le parezca. Es así? bajo mi punto de vista faltaría otra columna para agrupar los registros por filas.

Es más, ejecutar la cosulta 3 veces seguidas podría dar resultados diferentes.

Saludos
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino -
Responder Con Cita
  #10  
Antiguo 29-01-2020
Avatar de fjcg02
[fjcg02] fjcg02 is offline
Miembro Premium
 
Registrado: dic 2003
Ubicación: Zamudio
Posts: 1.410
Poder: 22
fjcg02 Va camino a la fama
Quiero decir que me parece más razonable que sea algo así

FECHA Europeas, Generales,
2015 100 200
2016 50 70
2018 200 175
...

por lo tanto te tiene que faltar algún campo. Y si es así, te falta el group by.

Código SQL [-]
SELECT
     Año, 
      CASE WHEN A.Proceso = 3 THEN A.Votos2 END Europeas,
       CASE WHEN A.Proceso = 4 THEN A.Votos2 END Generales,
       CASE WHEN A.Proceso = 5 THEN A.Votos2 END Autonomicas,
       CASE WHEN A.Proceso = 6 THEN A.Votos2 END Municipales
  FROM SYSDBA122540 A
GROUP BY AÑO

o

Código SQL [-]
SELECT
       PARTIDO, 
       CASE WHEN A.Proceso = 3 THEN A.Votos2 END Europeas,
       CASE WHEN A.Proceso = 4 THEN A.Votos2 END Generales,
       CASE WHEN A.Proceso = 5 THEN A.Votos2 END Autonomicas,
       CASE WHEN A.Proceso = 6 THEN A.Votos2 END Municipales
  FROM SYSDBA122540 A
GROUP BY PARTIDO

a ver si avanzas...


Saludos
__________________
Cuando los grillos cantan, es que es de noche - viejo proverbio chino -
Responder Con Cita
  #11  
Antiguo 29-01-2020
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.040
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Con un campo fecha sale así, no sé si es lo que busca:


Responder Con Cita
  #12  
Antiguo 30-01-2020
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 Casimiro Notevi Ver Mensaje
Cambia el nombre de esa variable, ponle por ejemplo vproceso, es que tienes un campo que se llama igual.
Gracias. No es la primera vez que me dices lo mismo.
Responder Con Cita
  #13  
Antiguo 30-01-2020
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
Por partes. Antes que nada gracias a todos por la ayuda prestada y pediros disculpas por las molestias.
Cita:
Empezado por fjcg02 Ver Mensaje
Quiero decir que me parece más razonable que sea algo así

FECHA Europeas, Generales,
2015 100 200
2016 50 70
2018 200 175
...

por lo tanto te tiene que faltar algún campo. Y si es así, te falta el group by.
Efectivamente hay un campo más que no he dado cuenta de poner y que también se consulta; es un campo código que sirve de clave única. Y sobre lo del group by, con este código (o similar):
Código SQL [-]
SELECT Año, 
      CASE WHEN A.Proceso = 3 THEN A.Votos2 END Europeas,
       CASE WHEN A.Proceso = 4 THEN A.Votos2 END Generales,
       CASE WHEN A.Proceso = 5 THEN A.Votos2 END Autonomicas,
       CASE WHEN A.Proceso = 6 THEN A.Votos2 END Municipales
  FROM SYSDBA122540 A
GROUP BY AÑO
el SQL da un error:
Cita:
Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause).
Y es lógico porque no hay ningún campo que acumule (SUM, COUNT, etc.)
Cita:
Empezado por Casimiro Notevi Ver Mensaje
Con un campo fecha sale así, no sé si es lo que busca:
El campo fecha sería el más lógico pero el problema es que no todos los procesos tienen lugar en el mismo año; así en España en el año 2019 han habido dos elecciones generales.
Responder Con Cita
  #14  
Antiguo 30-01-2020
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.040
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por Angel.Matilla Ver Mensaje
El campo fecha sería el más lógico pero el problema es que no todos los procesos tienen lugar en el mismo año; así en España en el año 2019 han habido dos elecciones generales.
No es problema, era solo un ejemplo, las fechas pueden ser del mismo año: 20190501, 20190623, 20190625, etc.
Responder Con Cita
  #15  
Antiguo 30-01-2020
ASAPLTDA ASAPLTDA is offline
Miembro
 
Registrado: jun 2003
Ubicación: COLOMBIA-CALI
Posts: 639
Poder: 21
ASAPLTDA Va por buen camino
Question Posible Solucion

NO SE SI ESTO TE SIRVA, PUEDE SER LENTO SI LA TABLA ORIGEN ES MUY GRANDE

SELECT
(SELECT COUNT(*) FROM INMOV where INCODTRA = '1') ENTRADAS,
(SELECT COUNT(*) FROM INMOV where INCODTRA = '2') REUBICACION,
(SELECT COUNT(*) FROM INMOV where INCODTRA = '3') SALIDAS
FROM RDB$DATABASE

RDB$DATABASE <--- TIENE UN SOLO REGISTRO

AHORA PUEDES HACER TAMBIEN
WITH TABLA AS(
SELECT
(SELECT COUNT(*) FROM INMOV where INCODTRA = '1') ENTRADAS,
(SELECT COUNT(*) FROM INMOV where INCODTRA = '2') REUBICACION,
(SELECT COUNT(*) FROM INMOV where INCODTRA = '3') SALIDAS
FROM RDB$DATABASE)
SELECT * FROM TABLA
Responder Con Cita
  #16  
Antiguo 30-01-2020
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.040
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por ASAPLTDA Ver Mensaje
NO SE SI ESTO TE SIRVA, PUEDE SER LENTO SI LA TABLA ORIGEN ES MUY GRANDE
Se ve que eres novato por aquí, escribiendo en mayúsculas y sin etiquetas de código
No te doy el enlace a la guía de estilo porque ya sabes dónde está
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
Query con pivote: No termino de entenderlo Angel.Matilla Firebird e Interbase 16 17-01-2020 18:06:25
Query con pivote Angel.Matilla Firebird e Interbase 2 02-01-2020 15:58:44
Con que sigo? serfap Varios 6 12-06-2006 18:02:58
sigo con MDI pablo OOP 2 27-02-2005 17:42:15
Sigo con mis preguntitas!!! Critter Varios 1 15-12-2004 21:44:05


La franja horaria es GMT +2. Ahora son las 17:08:35.


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