Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Problema de ordenación en campo varchar (https://www.clubdelphi.com/foros/showthread.php?t=85766)

José Luis Garcí 30-04-2014 10:57:20

Problema de ordenación en campo varchar
 
Hola compañeros, os planteo un nuevo problema que tengo en SQL, hasta ahora, ordenar el código de clientes, me resultaba fácil, ya que cogía el orden del ID, pero en esta consulta, no tengo acceso al ID de clientes, además, la consulta puede variar el orden de introducción a voluntad del cliente, bueno os pongo una pantalla



Como veis son datos de ejemplos, pero partiendo de datos reales, por lo que he ocultado los nombres de los clientes que si son reales, veréis que esta elegido por orden de código de clientes, pero no sale como deseaba.

La sentencia SQL es la que veis en este caso.

Código SQL [-]
SELECT FACTURA.CODIGOCLIENTE, CLIENTES.NOMBRE, FACTURA.SERIE, FACTURA.NUMERO, FACTURA.FECHA,  FACTURA.RECARGOEQUIVALENCIA, FACTURA.TOTALIMPUESTOS, 
FACTURA.TOTALCOMISION, (FACTURA.TOTAL) AS SUMATOTAL, FACTURA.CODIGOAGENTE, EMPLEADOS.NOMBRE FROM FACTURA 
INNER JOIN CLIENTES ON (FACTURA.CODIGOCLIENTE=CLIENTES.CODIGO) 
INNER JOIN EMPLEADOS ON (FACTURA.CODIGOAGENTE=EMPLEADOS.CODIGO) 
WHERE (FACTURA.FECHA BETWEEN '4/1/2014' AND '4/30/2014') ORDER BY FACTURA.CODIGOCLIENTE


HE probado con

Código SQL [-]
 CAST(FACTURA.CODIGOCLIENTE aS CODIGOCLIENTE)

Antes del form, pero cuando le digo que ordene me dice que CODIGOCLIENTE no se encuentra

Probando con


Código SQL [-]
SELECT FACTURA.CODIGOCLIENTE, CLIENTES.NOMBRE, FACTURA.SERIE, FACTURA.NUMERO, FACTURA.FECHA,  FACTURA.RECARGOEQUIVALENCIA, FACTURA.TOTALIMPUESTOS, 
FACTURA.TOTALCOMISION, (FACTURA.TOTAL) AS SUMATOTAL, FACTURA.CODIGOAGENTE, EMPLEADOS.NOMBRE FROM FACTURA
INNER JOIN CLIENTES ON (FACTURA.CODIGOCLIENTE=CLIENTES.CODIGO)
INNER JOIN EMPLEADOS ON (FACTURA.CODIGOAGENTE=EMPLEADOS.CODIGO)
WHERE (FACTURA.FECHA BETWEEN '4/1/2014' AND '4/30/2014')  AND
((FACTURA.CODIGOCLIENTE>='aaa') AND (FACTURA.CODIGOCLIENTE>='ZZZ'))
ORDER BY CODIGOCLIENTE

Me acepta la consulta pero no me da datos ninguno

El problema es que el código de cliente normalmente es número únicamente, pero podría contener otros caracteres en cualquier momento, ya que un cliente con dos centros podría ser 185 y 185-2 ó 185-B

El resultado actual es el que veis en la imagen y lo que espero es

1
2
3
4
etc

y no

1
10
100
etc

Espero haberme explicado bien, como siempre firebird 2.5 y Delphi 2010, gracias por vuestra ayuda

Casimiro Notevi 30-04-2014 11:14:07

¿codigocliente es varchar?, puedes hacer cast(codigocliente) as integer
Aunque también puedes ordernar por cliente.id (si es lo que necesitas)
Código SQL [-]
ORDER BY CLIENTE.ID

José Luis Garcí 30-04-2014 11:31:06

Cita:

Empezado por Casimiro Notevi (Mensaje 475869)
¿codigocliente es varchar?, puedes hacer cast(codigocliente) as integer
Aunque también puedes ordernar por cliente.id (si es lo que necesitas)
Código SQL [-]
ORDER BY CLIENTE.ID


Casimiro una pregunta si uso el hacer cast(codigocliente) as integer le dara lo mismo si tiene letras?

Casimiro Notevi 30-04-2014 11:34:18

Hombre, puedes probarlo, pero si tiene letras entonces no saldrá ordenado "numéricamente" :)
Usa lo que te he indicado en el order by, será más rápido y seguro.

José Luis Garcí 30-04-2014 11:37:15

He probado como me has dicho con el cast y me da error, puedes mirar haber si es que lo he montado mal




También he probado con el
Código SQL [-]
ORDER BY CLIENTE.ID

y perfecto, gracias maestro, sólo me queda la duda del Cast

Casimiro Notevi 30-04-2014 11:40:09

je, je... te he dicho que lo probaras para que vieras el resultado :) como has comprobado, no puedes hacer un cast a numérico de una letra.

José Luis Garcí 30-04-2014 11:44:24

Pero seguro que hay alguna manera de poder hacerlo, ahora es curiosidad, más que nada, seguiré investigando cuando pueda, salvo que algún compañero, nos muestre el camino.

Gracias Antonio.

ecfisa 30-04-2014 20:37:03

Cita:

Empezado por José Luis Garcí (Mensaje 475868)
...
El problema es que el código de cliente normalmente es número únicamente, pero podría contener otros caracteres en cualquier momento, ya que un cliente con dos centros podría ser 185 y 185-2 ó 185-B
...

Hola José.

Si el código se compone de números solamente se soluciona rellenando con caracteres por la izquierda.
Teniendo los valores: 10, 1, 22 15, 100, 189, 33, 181 en la columna CODIGO, esta consulta:
Código SQL [-]
SELECT CODIGOCLIENTE /* 6 caracteres para el ejemplo */
FROM CLIENTES
ORDER BY SUBSTRING('000000' FROM 1 FOR 6 - CHAR_LENGTH(CODIGOCLIENTE)) || CODIGOCLIENTE
devuelve: 1, 10, 15, 22, 33, 100, 181, 189 que es lo que buscas.

Pero si el código es alfanumérico no le veo la vuelta... Ya que por ejemplo 185-B, qudará siempre detrás de cualquier valor numérico de 4 dígitos (9999) y no detrás 185 como se esperaría.

Claro que lo anterior no tiene sentido, por que si fueran sólo números bastaría con declarar CODIGO como INTEGER y ordenarlos numericamente... :) es sólo para graficar la imposibilidad de ordenar "numericamente" datos alfanuméricos.

Saludos :)

fjcg02 30-04-2014 23:06:03

LO tienes chungo abuelete, ya te veo poniendo un campo para indicar el centro de aquellos clientes que tienen varios.

otra solución sería formatear los códigos cuando los introduces con trigger o similar algo así como

0000001-00
0000002-00
0000002-01
0000002-02
0000185-00
0000185-01
...

Un personaje que trabajaba conmigo quería que los códigos de los clientes se renumeraran si se borraba alguno, para que siempre salieran numerados en orden sin saltos.

No entendía que si en su día se dió de alta es porque era necesario, y tenía un presupuesto, pedido o factura y no se puede borrar.

Saludos

José Luis Garcí 01-05-2014 08:43:55

Cita:

Empezado por ecfisa (Mensaje 475896)
Hola José.

Si el código se compone de números solamente se soluciona rellenando con caracteres por la izquierda.
Teniendo los valores: 10, 1, 22 15, 100, 189, 33, 181 en la columna CODIGO, esta consulta:
Código SQL [-]
SELECT CODIGOCLIENTE /* 6 caracteres para el ejemplo */
FROM CLIENTES
ORDER BY SUBSTRING('000000' FROM 1 FOR 6 - CHAR_LENGTH(CODIGOCLIENTE)) || CODIGOCLIENTE
devuelve: 1, 10, 15, 22, 33, 100, 181, 189 que es lo que buscas.

Pero si el código es alfanumérico no le veo la vuelta... Ya que por ejemplo 185-B, qudará siempre detrás de cualquier valor numérico de 4 dígitos (9999) y no detrás 185 como se esperaría.

Claro que lo anterior no tiene sentido, por que si fueran sólo números bastaría con declarar CODIGO como INTEGER y ordenarlos numericamente... :) es sólo para graficar la imposibilidad de ordenar "numericamente" datos alfanuméricos.

Saludos :)

La verdad es que es más complicado de lo que pensaba, al final me veo , creando un campo auxiliar, de tipo integer, que guarde el código numérico y evito el problema

Cita:

Empezado por fjcg02 (Mensaje 475899)
LO tienes chungo abuelete, ya te veo poniendo un campo para indicar el centro de aquellos clientes que tienen varios.

otra solución sería formatear los códigos cuando los introduces con trigger o similar algo así como

0000001-00
0000002-00
0000002-01
0000002-02
0000185-00
0000185-01
...

Un personaje que trabajaba conmigo quería que los códigos de los clientes se renumeraran si se borraba alguno, para que siempre salieran numerados en orden sin saltos.

No entendía que si en su día se dió de alta es porque era necesario, y tenía un presupuesto, pedido o factura y no se puede borrar.

Saludos

Esa discusión la he tenido yo, pongo el botón borrar en los ABM, aunque les recomiendo encarecidamente que usen el campo fecha de baja, en vez de borrar, de hecho en facturas, etc, lo que hago es cambiar el estado de un documento, pero no permito borrarlo, sólo poner su estado en nulo, no veas la que me armo mi antiguo jefe hace un porrón de años.

De todas maneras los documentos vinculados a tablas como clientes, artículos etc, he optado, por guardar el código y la descripción, en la tabla, independientemente de la original, por si la eliminan.

Gracias a ambos, por vuestra ayuda.


La franja horaria es GMT +2. Ahora son las 06:55:09.

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