PDA

Ver la Versión Completa : Filas a Columnas


amerika111
07-04-2011, 03:11:32
Hola que tal tengo una situacion me gustaria saber como hacer para que me aparescan las filas a columnas.

por que tengo el siguiente resultado con un select e inner join que utilizo



CONCEPTOS IDEMPLEADO CANTIDADES
123 4524 120
345 4524 45
456 4524 10
785 4524 45


y e leido algo de pivot pero no lo reconoce el firebird

fjcg02
07-04-2011, 08:42:22
Todo tuyo...

http://www.clubdelphi.com/foros/showthread.php?t=63336&highlight=fjcg02

Saludos

oscarac
07-04-2011, 17:45:57
pero.. y que columnas quieres?
que codigo tiene tu consulta...
un poco mas de detalle por favor

amerika111
07-04-2011, 18:51:41
select * FROM CONCEPTOS_NO INNER JOIN PAGOS_NOMINA_DET
on PAGOS_NOMINA_DET.CONCEPTO_NO_ID = CONCEPTOS_NO.CONCEPTO_NO_ID INNER JOIN EMPLEADOS
ON EMPLEADOS.EMPLEADO_ID = PAGOS_NOMINA_DET.EMPLEADO_ID INNER JOIN PAGOS_NOMINA
ON EMPLEADOS.EMPLEADO_ID = PAGOS_NOMINA.EMPLEADO_ID where PAGOS_NOMINA.NOMINA_ID=83858



y esto despliega asi en general

Conceptos Monto Epleados
x1_________ 8.50___ 555
x2_________ 5.50___ 555
x3_________ 6.50___ 555
x4_________ 2.50___ 555
x1_________ 8.50___ 666
x2_________ 5.50___ 666
x3_________ 6.50___ 666
x4_________ 2.50___ 666

y quisiera que se agrupara por empleado pero no logro hacerlo y que los conceptos aparescan como columnas

Empleados x1 x2 x3 x4
555________ 8.50__5.50_6.50_2.50
666________ 8.50__5.50_6.50_2.50

oscarac
07-04-2011, 19:13:23
Puedes hacer algo asi como esto (usare campos imaginarios)


Select Id_empleado,
Case when Campo = 'x1', campoimporte else 0 end as x1,
Case when Campo = 'x2', campoimporte else 0 end as x2,
Case when Campo = 'x3', campoimporte else 0 end as x3,
Case when Campo = 'x4', campoimporte else 0 end as x4
from ....


el problema con esta consulta es que debes conocer de antemano cada uno de los conceptos (campo)

amerika111
07-04-2011, 20:20:14
Puedes hacer algo asi como esto (usare campos imaginarios)


Código Delphi [-] (http://www.clubdelphi.com/foros/#)
Select Id_empleado,
Case when Campo = 'x1', campoimporte else 0 end as x1,
Case when Campo = 'x2', campoimporte else 0 end as x2,
Case when Campo = 'x3', campoimporte else 0 end as x3,
Case when Campo = 'x4', campoimporte else 0 end as x4
from ....





el problema con esta consulta es que debes conocer de antemano cada uno de los conceptos (campo)


y esto como lo podria integrar a el query que muestro arriba,, lo ingresaria des pues del where o despues de los inner join...

Gallosuarez
07-04-2011, 20:22:33
amerika111:

Ese problema lo solucionas con CTE (Common Table Expressions), que es el equivalente al uso de PIVOT para otras bases de datos.

Aque viene un ejemplo de su uso:
http://www.firebirdsql.org/refdocs/langrefupd21-select.html#langrefupd21-select-cte

Saludos,
Gerardo Suárez Trejo

fjcg02
07-04-2011, 22:16:37
Todo tuyo...

http://www.clubdelphi.com/foros/showthread.php?t=63336&highlight=fjcg02

Saludos

Me reitero como la sidra el gaitero.

He ahí la solución. Aunque no entiendas ni un carajo, si entiendes cómo se hace la llamada, ya tienes lo que quieres. La procedure te devuelve la query montada, que será la que tienes que ejecutar.

Saludos

amerika111
07-04-2011, 22:23:40
Me reitero como la sidra el gaitero.

He ahí la solución. Aunque no entiendas ni un carajo, si entiendes cómo se hace la llamada, ya tienes lo que quieres. La procedure te devuelve la query montada, que será la que tienes que ejecutar.

Saludos


si ya cheque tu procedimiento pero es que no necesito sumar nada toda la info ya la tengo en tablas nadas mas que nose como acomodarla por empleado... ahorita el empleado se repite tantas veces tenga conceptos de pago si tiene 8 conceptos me aparece 8 veces por que los conceptos me aparecen en filas y no en columnas

oscarac
07-04-2011, 22:37:59
mmm si pudieras exportar tus tablas a un... no se access quiza y poder mandarlar para ver que se puede hacer

fjcg02
07-04-2011, 22:40:30
Pongamos luz en el asunto...

Espero que tengas algo de destreza.

Ejecuta la sentencia para que te cree la procedure CREARPIVOTE

Una vez tengas creado el procedimiento, llama al mismo con estos parámetros ( ten en cuenta que estoy suponiendo algunas cosas )


CREARPIVOTE ( 'TUTABLA','IDEMPLEADO','CONCEPTOS','MONTO','CONDICIONES')

TUTABLA será la tabla + las inner joins de todas las tablas que intervienen
IDEMPLEADO es el campo por el que quieres agrupar las filas
CONCEPTOS es el campo que quieres que pase de filas a columnas. No debiera haber demasiados conceptos en la tabla.
MONTO es el campo que quieres sumar por cada CONCEPTO ( El procedimiento sólo suma )
CONDICIONES filtro que aplica si procede Fecha desde hasta, ...

el resultado es una cadena con la query generada. Será algo del tipo...

Select IDEMPLEADO,
sum(Case when Campo = 'x1', MONTO else 0 end as x1,
sum(Case when Campo = 'x2', MONTO else 0 end as x2,
sum(Case when Campo = 'x3', MONTO else 0 end as x3,
sum(Case when Campo = 'x4', MONTO else 0 end as x4,
...
from TUTABLA
WHERE CONDICIONES



...que es lo que propone oscarac, lo que pasa es que es automático, y no debes saber el nº de columnas de antemano.

Luego copias esa select y la ejecutas en el ibexpert o en editor que utilices.

Ya nos dirás.

Saludos

oscarac
07-04-2011, 22:47:53
se ve interesante
pero... debe existir alguna otra forma...
aunque si amerika111 no tiene problemas podria llamar a ese procedimiento y como dices tu armar la cadena y listo:rolleyes:

fjcg02
07-04-2011, 23:00:45
se ve interesante
pero... debe existir alguna otra forma...
aunque si amerika111 no tiene problemas podria llamar a ese procedimiento y como dices tu armar la cadena y listo:rolleyes:

Sí, creo que podría hacerlo. Si os fijais, es muy sencillo añadir un parámetro más para permitir hacer sumas, medias, minimos o máximos.

Se ve interesante el tema del WITH [RECURSIVE] pero a estas horas no tengo el cuerpo para jotas. Además, es para FB 2.1 o superior, por lo que no sirve para todas las versiones.

Saludos

amerika111
07-04-2011, 23:17:04
pues trate de hacerlo asi pero nop no error tras error....

WITH EMPLEADO_ID AS (
SELECT NOMBRE_COMPLETO,PUESTO_NO_ID,DEPTO_NO_ID,SALARIO_DIARIO
FROM EMPLEADOS
GROUP BY EMPLEADOS.EMPLEADO_ID
)
SELECT DISTINCT DIAS_TRAB,HORAS_TRAB,HORAS_EXT,FORMA_PAGO
FROM PAGOS_NOMINA
LEFT JOIN EMPLEADOS
ON PAGOS_NOMINA.EMPLEADO_ID = EMPLEADOS.EMPLEADO_ID
LEFT JOIN PAGOS_NOMINA_DET
ON CONCEPTOS_NO.CONCEPTO_NO_ID=PAGOS_NOMINA_DET.CONCEPTO_NO_ID ;




subo el diagrama que mas o menos lo tengo asi... para saber si se puede realizar, con este codigo me despliega todos los conceptos del empleado en forma de filas si cuenta con 8 conceptos repite al empleado 8 veces por que cada concepto viene con empleadoid, entonces por eso queria ver la forma de pasar los conceptos a columnas y que empleados aparecienran en filas.

SELECT * FROM CONCEPTOS_NO INNER JOIN PAGOS_NOMINA_DET
on PAGOS_NOMINA_DET.CONCEPTO_NO_ID = CONCEPTOS_NO.CONCEPTO_NO_ID INNER JOIN EMPLEADOS
ON EMPLEADOS.EMPLEADO_ID = PAGOS_NOMINA_DET.EMPLEADO_ID INNER JOIN PAGOS_NOMINA
ON EMPLEADOS.EMPLEADO_ID = PAGOS_NOMINA.EMPLEADO_ID where PAGOS_NOMINA.NOMINA_ID=83858

oscarac
07-04-2011, 23:55:35
mmmm que base de datos Usas?
quiza sea absurda la pregunta pero quiero estar seguro

amerika111
07-04-2011, 23:56:46
mmmm que base de datos Usas?
quiza sea absurda la pregunta pero quiero estar seguro

Microsip con firebird

Gallosuarez
08-04-2011, 02:41:25
amerika111:

Lo sorprendente sería que dijeras que ese código te hubiera funcionado. Mira, no creo que estés entendiendo el concepto de CTE's (veo que, además de estar pésimamente implementado, el concepto no se está entendiendo).

Por otro lado, en este mismo foro ya se había tratado este tema con anterioridad. El compañero fjcg02 mencionó entonces en aquella ocasión que utilizar CTE's no resolvía el problema si existían varios conceptos. Lo cual no es un problema, puesto que se resuelve utilizando bloques ejecutables (Execute Block). Que es mas o menos lo que él hace en dicho procedimiento almacenado, con la diferencia que el código resultante es sumamente robusto y eficiente (amen de ser una solución elegante). Otra cosa, el código completo se puede armar desde la misma aplicación (ventaja de hacerlo con Execute block).

Bueno, hecha esta aclaración le digo a amerika111 que primero tiene que entender bien el concepto. Resolver su problema no debe de llevarse mucho tiempo.

Saludos,
Gerardo Suárez Trejo
PD. Estoy creando tutoriales que tratan todas estas cuestiones ... espero pronto subirlos para haber si les puede ser útiles a alguien... saludos nuevamente ...

fjcg02
08-04-2011, 08:24:12
bbbbbbbbbbbbbbbbbbbbbbbbbb

fjcg02
08-04-2011, 09:24:17
bbbbbbbbbbbbbbbbbbbbbbbbbb

Llevo un rato intentando entender el WITH este del demonio, y no acabo de cogerle el punto ... :confused::confused:

guillotmarc
08-04-2011, 09:49:25
En mi opinión os estáis complicando mucho. Solucionarlo con subconsultas normalmente es bastante sencillo (claro que solo se puede hacer cuando el nº de columnas está prefijado de antemano).

Sería algo del tipo :


select mes
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'A') as ventas_A,
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'B') as ventas_B,
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'C') as ventas_C
from meses


Saludos.

fjcg02
08-04-2011, 09:55:42
Hola de nuevo,
estoy haciendo unas pruebas, y la verdad, no me están convenciendo. A no ser que esté haciendo algo mal, y que agradecería que me lo indicarais si alguien lo sabe.

Mi intención es sacar una consulta con las poblaciones y los estados civiles de los clientes. La tabla es de clientes, en donde hay id, nombre, población y estado civil. La tabla tiene 16.500 registros. Existen 4 estados civiles ,a saber: CASADO, SOLTERO, SIN DEF. y VIUDO ( tened en cuenta que no está en producción, son pruebas :)).

Una primera consulta sería

select poblacion,
sum ( case when estadocivil='CASADO' then 1 ELSE 0 END) AS CASADO,
sum ( case when estadocivil='SOLTERO' then 1 ELSE 0 END) AS SOLTERO,
sum ( case when estadocivil='SIN DEF.' then 1 ELSE 0 END) AS SINDEF,
sum ( case when estadocivil='VIUDO' then 1 ELSE 0 END) AS VIUDO
from cliente
group by poblacion

Respuesta perfecta, tiempo de consulta aprox 3 segundos.

Utilizando WITH


with
estadosciviles as (
select estadocivil as EC, count(idcliente) as NUMERO
from cliente
group by estadocivil)
select poblacion,
ECC.numero as CASADOS,
ECS.numero as SOLTEROS,
ECSD.numero as SINDEF,
ECV.numero as VIUDOS
from cliente C
left join estadosciviles ECC on C.estadocivil=ECC.EC
and ECC.EC='CASADO'
left join estadosciviles ECS on C.estadocivil=ECS.EC
and ECS.EC='SOLTERO'
left join estadosciviles ECSD on C.estadocivil=ECSD.EC
and ECSD.EC='SIN DEF.'
left join estadosciviles ECV on C.estadocivil=ECV.EC
and ECV.EC='VIUDO'

Resultado inexacto. Me devuelve más de una fila por población, y datos un poco extraños.
Tiempo de respuesta. Me deja el equipo cuajado un par de minutos al menos.

Me da la sensación de que estoy haciendo mal la consulta. A ver si alguien me puede poner luz...

Gracias

guillotmarc
08-04-2011, 11:56:32
Hola.

Si en tu primero consulta, sencilla, ya obtienes el resultado el resultado que estás buscando, y en un tiempo óptimo, ¿ porqué te quieres complicar la vida sacándolo mediante CTE's ?.

NOTA: Para agilizar un poco más esa primera consulta, puedes añadir un índice por población (de esa forma facilitas la agrupación por ese campo).

Saludos.

fjcg02
08-04-2011, 13:28:57
Hola.

Si en tu primero consulta, sencilla, ya obtienes el resultado el resultado que estás buscando, y en un tiempo óptimo, ¿ porqué te quieres complicar la vida sacándolo mediante CTE's ?.

NOTA: Para agilizar un poco más esa primera consulta, puedes añadir un índice por población (de esa forma facilitas la agrupación por ese campo).

Saludos.

Hola,
estoy comparando la manera de obtener los datos, con la primera consulta ( que la creo dinámicamente con una procedure ) o con CTE's.
La segunda opción me está dando un rendimiento muy pobre, de ahí mi consulta de si estoy haciendolo bien o no.

Saludos

Gallosuarez
08-04-2011, 16:48:38
Hola.
Si en tu primero consulta, sencilla, ya obtienes el resultado el resultado que estás buscando, y en un tiempo óptimo, ¿ porqué te quieres complicar la vida sacándolo mediante CTE's ?.


No estoy muy de acuerdo en que utilizar CTE's te compliques la vida ... hagamos lo siguiente:

fjcg02 puedes poner la estructura de tus tablas (algo así como lo que hizo amerika111, en un archivo gpeg como el que ella subio). Después hacemos el ejercicio y verán que es muy fácil.

El secreto está primero en programar la "tabla" que te servirá de pivote ... posteriormente lo único que tienes que hacer es llamarla las veces que necesites dependiendo de los "conceptos" que quieras que aparezcan en las columnas ... ¿me explico?.

Saludos
Gerardo Suárez Trejo

guillotmarc
08-04-2011, 17:37:43
Hola.

No estoy muy de acuerdo en que utilizar CTE's te compliques la vida ... hagamos lo siguiente:

Está claro que la vida no te la complican las herramientas (CTE's, subconsultas, vistas, SP's, etc. ...) sino que para eso ya nos bastamos nosotros mismos, con el uso que damos a estas herramientas. :)

En este caso tan sencillo parece que recurrir a CTE's es como intentar matar mosquitos a cañonazos.

Saludos.

guillotmarc
08-04-2011, 17:40:00
Hola.

Hola,
estoy comparando la manera de obtener los datos, con la primera consulta ( que la creo dinámicamente con una procedure ) o con CTE's.
La segunda opción me está dando un rendimiento muy pobre, de ahí mi consulta de si estoy haciendolo bien o no.


¿ Porqué necesitas construir dinámicamente la primera consulta ?. ¿ El número de columnas no es siempre fijo ?.

Saludos.

fjcg02
08-04-2011, 22:25:12
Hola,
respondiendo por partes.
1.- Estoy comparando la forma en la que genero las consultas tipo pivot con la forma que expone Gallosuarez ( WITH ).
2.- Obviamente, el problema surge cuando el nº de columnas no es fijo. Este dato es importante. Si no fuera por este pequeño detalle, no tendríamos que resolver nada.
3.- Cuando no conozco algo, empiezo por pruebas sencillas. De no ser así, difícilmente podré sacar conclusiones válidas. Ya me pondrán los usuarios pruebas difíciles, que para eso están.
4.- La estructura de mi única tabla de la que obtengo datos es la que he comentado :
- idcliente
- nombre
- Poblacion
- Estadocivil
- ... no ocupan el resto de campos.

Enunciado del problema: Dígame ud. cuantas personas hay por estado civil en cada una de las poblaciones.
Poblacion CASADOS SOLTEROS VIUDOS NOSABENOCONTESTA
Bilbao 5 7 3 50
Barakaldo 10 20 6 0
Zamudio 0 30 50 9
...

Vale, es un caso fácil, pero supongamos que no sabemos cuantos estados civiles existen.
El resto de la historia ya la conoceis. Soy todo 'oidos' a ver si consigo aprender cómo funcionan los CTE's. Estoy esperando esos tutoriales ... :rolleyes:

Saludos

amerika111
08-04-2011, 22:42:04
no pues sigo en las mismas, ya hasta regañada sali,


trate de hacerlo con lo de CTE's pero nada no se como utilizar lo que me han comentado del case o la subconsulta:o


with tabla as
(select PAGOS_NOMINA_DET.PAGO_NOMINA_ID, PAGOS_NOMINA_DET.CONCEPTO_NO_ID,CONCEPTOS_NO.NOMBRE,PAGOS_NOMINA_DET.IMPORTE,EMPLEADO_ID FROM PAGOS_NOMINA_DET INNER JOIN CONCEPTOS_NO
on CONCEPTOS_NO.CONCEPTO_NO_ID = PAGOS_NOMINA_DET.CONCEPTO_NO_ID )
SELECT (NOMBRE from tabla WHERE ) FROM tabla
select IMPORTE
(SELECT IMPORTE from tabla where CONCEPTO_NO_ID =104) as 'SALARIO MIN'
FROM tabla

amerika111
09-04-2011, 01:19:32
with tabla as
(select PAGOS_NOMINA_DET.PAGO_NOMINA_ID, PAGOS_NOMINA_DET.CONCEPTO_NO_ID,CONCEPTOS_NO.NOMBRE,PAGOS_NOMINA_DET.IMPORTE,EMPLEADO_ID FROM PAGOS_NOMINA_DET INNER JOIN CONCEPTOS_NO
on CONCEPTOS_NO.CONCEPTO_NO_ID = PAGOS_NOMINA_DET.CONCEPTO_NO_ID )

select IMPORTE
(SELECT IMPORTE from tabla where CONCEPTO_NO_ID =104) as 'SALARIO MIN'
FROM tabla

Gallosuarez
09-04-2011, 03:09:15
fjcg02:

Muy bien ... ahora ya nos estamos entendiendo ... bueno pues manos a lo obra:

Lo primero que hay que notar es que solo tienes una solo tabla, por lo que de ahí vamos a obtener el pivote ... y del pivote vamos a obtener nuestro resultado final. Por otro lado, es mejor empezar con un caso pequeño (donde los conceptos son fijos). Posteriormente nos movemos hacia un caso más difícil, ¿vale?.

Corre esta sentencia primero (este sería nuestro pivote). Sean benévolos conmigo a lo mejor tengo errores en el nombre de un tabla/campo, etc, etc. Necesito que me digas si funciona correctamente dicha sentencia.

SELECT
POBLACION,
ESTADOCIVIL,
COUNT(*) AS CANTIDAD
FROM CLIENTE
GROUP BY POBLACION, ESTADOCIVIL


Despues si todo esto se ejecutó sin errores (doy por hecho que así es), creo mi tabla principal donde aparecerán los conceptos.

WITH PIVOTE AS (
SELECT
POBLACION,
ESTADOCIVIL,
COUNT(*) AS CANTIDAD
FROM CLIENTE
GROUP BY POBLACION, ESTADOCIVIL
)
SELECT
P.POBLACION,
COALESCE(P_CASADOS.CANTIDAD, 0) AS CASADOS,
COALESCE(P_SOLTEROS.CANTIDAD, 0) AS SOLTEROS
FROM PIVOTE P
LEFT JOIN PIVOTE P_CASADOS
ON P.POBLACION = P_CASADOS.POBLACION
AND P_CASADOS.ESTADOCIVIL = 'Casado'
LEFT JOIN PIVOTE P_SOLTEROS
ON P.POBLACION = P_SOLTEROS.POBLACION
AND P_SOLTEROS.ESTADOCIVIL = 'Soltero'
.
.


Espero que esto despeje un poco sus dudas. Porqué decimos que esta forma de solucionar el problema es sumamente eficiente, porque la tabla "pivote" solo se ejecuta una sola vez, sin importar cuantos conceptos se agreguen después. Otra cosa que hay que hacer notar es el uso correcto de índices. En este caso no sé si haya indices, sino no los hay, la sentencia pivote tendrá que recorrer toda la tabla (aunque solo sea una solo vez).

Saludos,
Gerardo Suárez Trejo

guillotmarc
09-04-2011, 15:13:05
La verdad es que las CTE son interesantes, no las conocía (aún sigo con Firebird 2.0). Pero no parece que sirvan para solventar el problema que tenemos, puesto que al final, con los datos de la CTE acabas haciendo otra consulta, y esa no puede tener un número variable de columnas. Así que las CTE no parecen una alternativa al PIVOT. Al menos no parecen una alternativa mejor que una simple consulta con subconsultas o CASE's.

En el caso de que tengamos un número variable de columnas, sigo sin ver otra solución que la de construir dinámicamente la consulta.

Saludos.

fjcg02
10-04-2011, 15:14:39
Hola,
gracias por responder. He de decir que de la sentencia que ejecuto, me sorprenden dos cosas.
1.- La respuesta tarda muchísimo.
2.- EL resultado no es el que deseo. Me repite algunas poblaciones, por lo que no puedo dar por bueno el resultado.

la sentencia es la que me has comentado, Gallosuarez

with pivote as (select poblacion, estadocivil, count(idcliente) as cantidad
from cliente
group by poblacion, estadocivil
)

SELECT
P.POBLACION,
COALESCE(P_CASADOS.CANTIDAD, 0) AS CASADOS,
COALESCE(P_SOLTEROS.CANTIDAD, 0) AS SOLTEROS
FROM PIVOTE P
LEFT JOIN PIVOTE P_CASADOS
ON P.POBLACION = P_CASADOS.POBLACION
AND P_CASADOS.ESTADOCIVIL = 'CASADO'
LEFT JOIN PIVOTE P_SOLTEROS
ON P.POBLACION = P_SOLTEROS.POBLACION
AND P_SOLTEROS.ESTADOCIVIL = 'SOLTERO'

Un saludo

RONPABLO
10-04-2011, 19:58:14
Yo hago algo parecido y me toca que construirlo desde delphi, yo hago algo así como esto:



sql := '';
while not QConceptos.Eof do
begin
if sql <> '' then
sql := sql + ',';
Concepto := QConceptos.FieldByName('Concepto').AsString;
sql := sql + ' Case when Campo = ' + QuotedStr(Concepto) + ' THEN campoimporte else 0 end as ' + Concepto
QConceptos.Next;
end;

sql := 'Select Id_empleado, ' + sql + ' from ....'



Donde el query QConceptos es el siguiente:


Select distinct Concepto from Conceptos





Todo esto lo hago sin comprobar, es solo para dar una idea de como lo hago.

RONPABLO
10-04-2011, 20:11:32
En mi opinión os estáis complicando mucho. Solucionarlo con subconsultas normalmente es bastante sencillo (claro que solo se puede hacer cuando el nº de columnas está prefijado de antemano).

Sería algo del tipo :

select mes
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'A') as ventas_A,
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'B') as ventas_B,
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'C') as ventas_C
from meses


Saludos.


Viendo esta respuesta creo que combinándola con mi respuesta anterior podría también funcionar muy bien.

Gallosuarez
12-04-2011, 17:44:05
Hola,
gracias por responder. He de decir que de la sentencia que ejecuto, me sorprenden dos cosas.
1.- La respuesta tarda muchísimo.
2.- EL resultado no es el que deseo. Me repite algunas poblaciones, por lo que no puedo dar por bueno el resultado.


fjcg02:

1.- ¿Cual es el plan que está utilizando la sentencia? ¿te dice si utiliza índices?
2.- No, veo porqué la sentencia podría repetir algunas poblaciones, en todo caso me imagino que el problema puede ser que no haya consistencia en los datos que contiene tu tabla, ¿me explico?

¿Podrías subir una archivo .zip que contenga las sentencias INSERT de dicha tabla (al menos los campos que nos interesan en este ejercicio? (solo si puedes, claro), me gustaría echarle un vistazo a esos datos. Por otro lado, veo que tu tabla no está normalizada (no digo que sea malo o bueno, todo depende de la particularidades y necesidades de cada proyecto) ¿Existe alguna razón de tu parte para que hayas diseñado así dicha tabla?

Estoy en espera de tu respuesta ...

Saludos,
Gerardo Suárez Trejo

IVAND
19-04-2011, 15:59:07
Perdon si es que no estoy en el tema

Pero existen unos componentes llamados Devexpress (PivotGrid) , con eso tienes solucionados todos los problemas de este tipo

Al menos a mi me ha funcionado , no tienes que hacer nada complicado solo la simple consulta y el componente hace al resto

fjcg02
19-04-2011, 16:14:22
Hola,
perdonad que no haya respondido antes.

Todos los puntos que indica GalloSuarez son importantes a la hora de ejecutar la consulta. A saber, índices, normalización de tablas, ....

Independientemente de todos ellos, bajo mi modesta opinión, las dos consultas deberían ser de parecido rendimiento, segundo arriba segundo abajo, ya que usan el mismo origen de datos para extraer los resultados. Igual de optimizados o sin optimizar.

No sé si tendré tiempo para proporcionaros más datos en cuanto al plan de ejecución, ... , intentaré sacarlos.
No os puedo proporcionar los registros de la BBDD ya que son reales, de producción.

Respecto a los componentes de Devexpress-PivotGrid, si alguien está dispuesto a financiar el proyecto, pues podría proporcionarme una licencia legal para que pueda utilizarlos :D:D

Saludos

guillotmarc
19-04-2011, 21:06:49
Hola,
Respecto a los componentes de Devexpress-PivotGrid, si alguien está dispuesto a financiar el proyecto, pues podría proporcionarme una licencia legal para que pueda utilizarlos :D:D


Prueba esta variante open-source.

http://sourceforge.net/projects/fxds/

NOTA: ¿ Puedes decir porqué quieres usar CTE's ?, para este caso concreto sigo sin ver ninguna ventaja respecto a las subconsultas (y para el optimizador del motor de Firebird está claro que le resulta bastante más sencillo optimizar las subconsultas).

Saludos.

guillotmarc
19-04-2011, 21:13:28
Si quieres usar el mismo TDecisionCube integrado en Delphi, aquí tienes información para enlazarlo con Datasets que no provengan de BDE.

http://edn.embarcadero.com/article/27848

Y aquí tienes como compilar este mismo TDecisionCube propio de Delphi en versiones actuales de Delphi.

http://www.bobswart.nl/weblog/Blog.aspx?RootId=5:2050

fjcg02
20-04-2011, 08:22:46
NOTA: ¿ Puedes decir porqué quieres usar CTE's ?, para este caso concreto sigo sin ver ninguna ventaja respecto a las subconsultas (y para el optimizador del motor de Firebird está claro que le resulta bastante más sencillo optimizar las subconsultas).

Saludos.

Ya lo comenté ( eso creo ). Estoy jugando para ver las posibilidades, ya sé que no es el caso perfecto para probar. Si no sé hacer integrales, no voy a ponerme a hacer integrales diferenciales de cuarto grado... Pasito a pasito.

Gracias por los otros tres links, le echaré un vistazo.

Por otro lado, no es que saque chispas a los motores en cuanto a que utilizo los recursos más rebuscados, pero sí me gusta saber que existen por si en un futuro puedo aplicarlos en algún caso. Se todas maneras, soy de los que opino que recursos 'raros' los mínimos. Buen diseño de datos, buena elección de índices, y resultados rapiditos para los usuarios.

Un saludo

mRoman
18-03-2015, 20:08:52
En mi opinión os estáis complicando mucho. Solucionarlo con subconsultas normalmente es bastante sencillo (claro que solo se puede hacer cuando el nº de columnas está prefijado de antemano).

Sería algo del tipo :


select mes
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'A') as ventas_A,
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'B') as ventas_B,
(select sum(unidades) from ventas where ventas.mes = meses.mes and producto = 'C') as ventas_C
from meses


Saludos.

Hola guillotmarc, en que version de firebird puedes hacer esto?

Uso la version 2.0