Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   ¿Y por qué no funciona el ORDER BY? (https://www.clubdelphi.com/foros/showthread.php?t=96473)

Angel.Matilla 06-11-2023 12:56:06

¿Y por qué no funciona el ORDER BY?
 
Me vais a mandar a la porra, como poco, por pesado. El query que había planteado en los anteriores hilos ha quedado así al final:
Código SQL [-]
SELECT DISTINCT A.Codigo, A.Nombre, COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1) Municipio, C.Nombre NomMunicipio,
       (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Partido = A.Codigo AND Proceso = B.Proceso 
           AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1))) VotPar,
       RDB$SET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO', (SELECT FIRST 1 Municipio FROM Mesas WHERE CodPrv = B.CodPrv AND Codigo = B.Mesa ORDER BY Municipio))
FROM Partidos A
LEFT JOIN Resultados B ON A.CodPrv = B.CodPrv AND A.Codigo = B.Partido AND B.Proceso = :Proceso
LEFT JOIN Poblacion C ON A.CodPrv = C.CodPrv AND COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1) = C.Codigo
WHERE A.CodPrv = :PrvIns AND A.Codigo > 0 
  AND EXISTS (SELECT Municipio FROM Mesas WHERE CodPrv = B.CodPrv AND Codigo = B.Mesa)
ORDER BY 4, 5 DESC, 2
Dado que con ese query tengo que alimentar un TreeView me interesa añadir ese campo con los votos obtenidos. Funciona como un tiro gracias a la sugerencia de duilioisola pero me ocurre un cosa muy curiosa: no ordena bien todo. Fijaros en las filas destacadas:

A pesar de haber puesto como segundo campo de ordenación la suma de votos en orden descendente, hace lo que le da la gana

Casimiro Notevi 06-11-2023 15:33:37

¿Será porque es alfanumérico?

Angel.Matilla 06-11-2023 17:52:41

Cita:

Empezado por Casimiro Notevi (Mensaje 553146)
¿Será porque es alfanumérico?

Los campos 4 y 2 (Nombre del municipio y nombre del partido) sí lo son; el 5 (Votos) es entero. No obstante si ese fuera el problema, en el resto de municipios haría lo mismo y unos lo hace bien y otros no.

mamcx 06-11-2023 18:25:57

El `order by` como lo muestras esta correcto. La BD no se esta inventando eso. El problema es que no es el orden que estas buscando. Supongo que quires el `total de votos ascendente por municipio`?

Angel.Matilla 06-11-2023 18:26:54

Cita:

Empezado por mamcx (Mensaje 553154)
El `order by` como lo muestras esta correcto. La BD no se esta inventando eso. El problema es que no es el orden que estas buscando. Supongo que quires el `total de votos ascendente por municipio`?

Efectivamente, eso es lo que quiero

Casimiro Notevi 06-11-2023 20:10:23

Es que al tener el ORDER BY 4, 5 DESC, 2 están priorizando el 4 ( NomMunicipio) antes que VotPar.
Si quieres ordenar por VotPar, entonces tendrás que poner 5, 4, etc...

delphi.com.ar 07-11-2023 03:57:41

Por lo que veo está bien la premisa, que el orden no parece correcto. Las columnas 4 y 5 serían "NOMMUNICIPIO" y "VOTPAR", y el resultado resumido a esas columnas es:
Código:

ABENOJAR  829
ABENOJAR  249
AGUDO      170
AGUDO      212

Pero debería ser:
Código:

ABENOJAR  829
ABENOJAR  249
AGUDO      212
AGUDO      170

Donde la segunda columna es VOTPAR y debería estar ordenada en forma descendiente para cada ministerio, pero eso no se evidencia en el segundo caso. Desde mi desconocimiento de Firebird/Interbase, pero conociendo otros motores, sospecharía si la columna municipio no tiene alguna diferencia no visible en el campo del municipio. Desde caracteres especiales hasta mas espacios al final del texto. Una forma simple de ver eso es quitar el DESC del orden, y ver si mantiene la misma lógica. Otra forma es hacer un UPDATE del primer registro, sobre el segundo. Es importante aclarar que desconozco el modelo de datos como para saber si el valor pertenece a registros distintos.

La segunda columna es el resultado de un SUM así que dudo que sea alfanumérico.

Angel.Matilla 07-11-2023 09:43:52

Gracias por vuestras respuestas.
Cita:

Empezado por Casimiro Notevi (Mensaje 553158)
Es que al tener el ORDER BY 4, 5 DESC, 2 están priorizando el 4 ( NomMunicipio) antes que VotPar.
Si quieres ordenar por VotPar, entonces tendrás que poner 5, 4, etc...

No: necesito ordenar primero por el nombre municipio y, dentro de cada uno de ellos, por votos en orden descendente.
Cita:

Empezado por delphi.com.ar (Mensaje 553162)
sospecharía si la columna municipio no tiene alguna diferencia no visible en el campo del municipio

Ten en cuenta que el nombre del municipio se saca de otra tabla en el query, por lo tanto no puede haber diferencias entre las filas del mismo municipio en ese campo.
Cita:

Empezado por delphi.com.ar (Mensaje 553162)
Una forma simple de ver eso es quitar el DESC del orden, y ver si mantiene la misma lógica

Curiosamente si quito el DESC los que antes se ordenaban bien lo hacen mal y viceversa.

Cita:

Empezado por delphi.com.ar (Mensaje 553162)
Otra forma es hacer un UPDATE del primer registro, sobre el segundo.

Esto me lo tienes que explicar.

Lo único que se me ocurre es crear una tabla temporal, indexada por los campos que me interesan, y cargarla a partir de ese query.

fjcg02 07-11-2023 11:19:23

Al usar una SELECT para calcular el dato, el motor pasa.

Encapsula todo en una SELECT y prueba.

Código SQL [-]
SELECT A.*
FROM
(
SELECT DISTINCT A.Codigo, A.Nombre, COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1) Municipio, C.Nombre NomMunicipio,
       (SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Partido = A.Codigo AND Proceso = B.Proceso 
           AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1))) VotPar,
       RDB$SET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO', (SELECT FIRST 1 Municipio FROM Mesas WHERE CodPrv = B.CodPrv AND Codigo = B.Mesa ORDER BY Municipio))
FROM Partidos A
LEFT JOIN Resultados B ON A.CodPrv = B.CodPrv AND A.Codigo = B.Partido AND B.Proceso = :Proceso
LEFT JOIN Poblacion C ON A.CodPrv = C.CodPrv AND COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1) = C.Codigo
WHERE A.CodPrv = :PrvIns AND A.Codigo > 0 
  AND EXISTS (SELECT Municipio FROM Mesas WHERE CodPrv = B.CodPrv AND Codigo = B.Mesa)
) A
ORDER BY 4, 5 DESC, 2

Por otro lado, haces unas SELECT totalmente anárquicas, que me parece que penalizan totalmente el rendimiento.

Saludos

Angel.Matilla 07-11-2023 12:19:14

Cita:

Empezado por fjcg02 (Mensaje 553176)
Al usar una SELECT para calcular el dato, el motor pasa.

Encapsula todo en una SELECT y prueba.

Da este error:
Código:

Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Invalid command.
No column name specified for column number 6 in derived table A.

Cita:

Empezado por fjcg02 (Mensaje 553176)
Por otro lado, haces unas SELECT totalmente anárquicas, que me parece que penalizan totalmente el rendimiento.

No te quito la razón, y es lo que tiene haber aprendido a lo bestia directamente en "real".

fjcg02 07-11-2023 13:59:05

Hola,

supongo que ese error te da porque no pones nombre /alias a las columnas.

Código SQL [-]
SELECT DISTINCT 
A.Codigo, 
A.Nombre, 
COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1) Municipio, 
C.Nombre NomMunicipio,
(SELECT SUM(Votos) FROM Resultados WHERE CodPrv = A.CodPrv AND Partido = A.Codigo AND Proceso = B.Proceso 
       AND Mesa IN (SELECT Codigo FROM Mesas WHERE CodPrv = A.CodPrv AND Municipio = COALESCE(RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'), 1))) VotPar,
/* a partir de aqui puedes tener el problema */
RDB$SET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO', (SELECT FIRST 1 Municipio FROM Mesas WHERE CodPrv = B.CodPrv AND Codigo = B.Mesa ORDER BY Municipio)
) NOMBRECOLUMNA

FROM Partidos A

Te falta bautizar alguna columna para que lo entienda, concretamente la sexta columna. (Te respondo rápido sin analizar al 100% la consulta...)

Saludos

PD: ya he visto en otro hilo que empiezas a escribir consultas de forma más estructurada. De esa manera para el motor es más fácil.

delphi.com.ar 07-11-2023 14:54:44

Cita:

Empezado por Angel.Matilla (Mensaje 553171)
Esto me lo tienes que explicar.

Si el nombre del municipio no salía de una tabla normalizada, y había dos registros con el mismo nombre, me refería a actualizar uno contra el otro. Pero por lo que cuentas no tiene sentido.

Solo para reforzar la idea, ¿Qué pasa si ordenas ORDER BY 4 DESC, 5, 2?.. porque si el fenómeno se repite invertido, entonces sigo sospechando del primer campo (4).

Angel.Matilla 07-11-2023 18:25:46

Cita:

Empezado por fjcg02 (Mensaje 553181)
Te falta bautizar alguna columna para que lo entienda, concretamente la sexta columna. (Te respondo rápido sin analizar al 100% la consulta...)

Saludos

PD: ya he visto en otro hilo que empiezas a escribir consultas de forma más estructurada. De esa manera para el motor es más fácil.

La sexta columna del query es la definición de una variable (RDB$SET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO'...), que se usa para recuperar un valor (RDB$GET_CONTEXT('USER_TRANSACTION', 'MUNICIPIO')). Fuera de eso todas las columnas están identificadas. Al margen de esa circunstancia, esa columna no interviene para nada en el ORDER BY y por lo tanto debería dar lo mismo que estuviera bautizada o no; además esa columna siempre tiene valor 1.

Angel.Matilla 07-11-2023 18:31:03

Cita:

Empezado por delphi.com.ar (Mensaje 553182)
Solo para reforzar la idea, ¿Qué pasa si ordenas ORDER BY 4 DESC, 5, 2?.. porque si el fenómeno se repite invertido, entonces sigo sospechando del primer campo (4).

Hace más o menos lo mismo: Ordena bien por el nombre del municipio, perocon los votos hace lo que le da la gana.

Angel.Matilla 07-11-2023 18:46:18

Cita:

Empezado por delphi.com.ar (Mensaje 553182)
Solo para reforzar la idea, ¿Qué pasa si ordenas ORDER BY 4 DESC, 5, 2?.. porque si el fenómeno se repite invertido, entonces sigo sospechando del primer campo (4).

Para más inri todavía no veo como demonios está ordenando la salida: ni por código de partido (columna 1), ni por su nombre, ni por el código de municipio, etc. A saber que está interpretando el motor.
Añadido a esto: la tercera columna es el código de municipio y resulta que en los primeros registros que se ven ahí está el mismo nombre (VISO DEL MARQUÉS) pero hay dos códigos diferentes: 57486, que es el que le corresponde, y 1217, que es de Alcázar de San Juan. Pero encima ese 57846 aparece más adelante en Villarta de San Juan. Cada vez lo entiendo menos.

Casimiro Notevi 07-11-2023 20:52:32

Creo que es mejor que empieces por lo básico, probar y si va bien entonces añades otra tabla, y así poco a poco.
Si falla en un momento verás dónde es. Pues al quitar lo que acabes de añadir volverá a ir bien.
No sé si puedes "anonimizar" los datos y poner la BD para que podamos probar.

mamcx 08-11-2023 00:29:35

Simplificado no es así?:

Código SQL [-]
WITH votos AS (
    SELECT 'POPULAR' AS partido, 'ABENOJAR' AS municipio, 829 AS votos
    UNION
    SELECT 'ALCAZAR', 'ABENOJAR', 249
    UNION
    SELECT 'POPULAR', 'AGUDO', 170
    UNION
    SELECT 'ALCAZAR', 'AGUDO', 212
)

SELECT municipio, partido, votos FROM votos
ORDER BY municipio, votos ASC, partido;


Código:

| municipio | partido | votos |
| --------- | ------- | ----- |
| ABENOJAR  | ALCAZAR | 249  |
| ABENOJAR  | POPULAR | 829  |
| AGUDO    | POPULAR | 170  |
| AGUDO    | ALCAZAR | 212  |


Angel.Matilla 08-11-2023 11:06:49

Cita:

Empezado por mamcx (Mensaje 553190)
Simplificado no es así?

¡Madre mía! Eso que sugieres ¿es recorrer toda la tabla e ir haciendo las asignaciones pertinentes?

mamcx 08-11-2023 14:56:40

No. solo puse un ejemplo reducido.

Angel.Matilla 08-11-2023 18:11:35

Cita:

Empezado por mamcx (Mensaje 553203)
No. solo puse un ejemplo reducido.

De todas maneras, lo que sugieres es ir leyendo todo para ponerlo en el SELECT. No tiene sentido o yo no he entendido la sugerencia.


La franja horaria es GMT +2. Ahora son las 09:40:59.

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