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)
-   -   Error en una condición con CAST (https://www.clubdelphi.com/foros/showthread.php?t=93025)

Angel.Matilla 24-04-2018 11:51:35

Error en una condición con CAST
 
Tengo una base de datos en FB 2.5. Dos de las tablas son: provincias, que únicamente contiene dos valores (Codigo SMALLINT y Nombre VARCHAR), y poblaciones que tiene, entre otros campos, el nombre y el código postal, ambos VARCHAR. En la tabla de provincias tengo declarada una fila con el código 99 y el nombre PROVINCIA DESCONOCIDA.

Estoy tratando de sacar las poblaciones con este query:
Código PHP:

SELECT CodigoNombreCpostal
  FROM Poblacion 
 WHERE CAST
(SUBSTRING(Cpostal FROM 1 FOR 2) AS INTEGERNOT IN (SELECT Codigo FROM Provincias WHERE Codigo <> 99)
 
ORDER BY NombreCpostalCodigo 

Sin embargo al ejecutar el query me da este error:
Cita:

Conversion error from string ""
¿Qué estoy haciendo mal?

Casimiro Notevi 24-04-2018 12:28:34

Está un poco confuso, ¿exactamente qué quieres conseguir?

Casimiro Notevi 24-04-2018 12:45:35

Pero, vamos, que el problema es que hay un cpostal en blanco:
Código:

13    14828    CINCO CASAS        ES
Como ejemplo ;)

duilioisola 24-04-2018 17:21:24

Como dice Casimiro, tienes un código postal en blanco.

Prueba concantenando '0' antes del código postal para que por lo menos tenga un 0.
Obviamente fallará si tienes letras en ese campo.

Código SQL [-]
SELECT CODIGO, NOMBRE, CPOSTAL
FROM POBLACION
WHERE
CAST(SUBSTRING('0' || CPOSTAL FROM 1 FOR 2) AS INTEGER) NOT IN (SELECT CODIGO
                                                                FROM PROVINCIAS
                                                                WHERE
                                                                CODIGO <> 99)
ORDER BY NOMBRE, CPOSTAL, CODIGO

Angel.Matilla 24-04-2018 19:22:03

Gracias por vuestras ideas.

Sobre lo del código postal en blanco: Vale. El ejemplo que ha puesto Casimiro es real: En esa tabla está ese municipio sin código postal, pero imagina que la carga desde un fichero externo TXT pone, por error, código postales que empiezan por 75 en lugar de 45. Para eso me hace falta ese query.
Cita:

Empezado por duilioisola (Mensaje 525848)
Prueba concantenando '0' antes del código postal para que por lo menos tenga un 0.
Obviamente fallará si tienes letras en ese campo.

Acabo de probarlo. No funciona; probando sobre la tabla que tengo me sale, por ejemplo, esto:
Cita:

SELECT CODIGO, NOMBRE, CPOSTAL FROM POBLACION
WHERE CAST(SUBSTRING('0' || CPOSTAL FROM 1 FOR 2) AS INTEGER) NOT IN (SELECT CODIGO
FROM PROVINCIA WHERE CODIGO < 99) ORDER BY NOMBRE, CPOSTAL, CODIGO

Codigo Nombre Cpostal
18 ABADIA LA MENA 09586
26 ABAJAS DE BUREBA 09141
...
Lo que me descuadra del todo es que poniendo ese cero no dé error y sin ponerlo, al menos a mi, sí me lo dé. :confused:

Angel.Matilla 24-04-2018 19:32:13

Cita:

Empezado por duilioisola (Mensaje 525848)
Prueba concantenando '0' antes del código postal para que por lo menos tenga un 0.
Obviamente fallará si tienes letras en ese campo.

De todas formas hay algo en tu query que no me cuadra. Haciendo una prueba a lo bruto:
Código PHP:

SELECT CODIGONOMBRECPOSTALCAST(SUBSTRING('0' || CPOSTAL FROM 1 FOR 2) AS INTEGERFROM POBLACION
WHERE CAST
(SUBSTRING('0' || CPOSTAL FROM 1 FOR 2) AS INTEGERNOT IN (SELECT CODIGO
FROM PROVINCIA WHERE CODIGO 
AND CODIGO 99ORDER BY CPOSTALNOMBRECODIGO 

Me sale, entre otras cosas, esto:
Cita:

Código Nombre
14828 CINCO CASAS Cpostal CAST
57931 VITORIA-GASTEIZ 01000 0
14221 CENTRO MILITAR ARACA/ARAKA 01100 0
...

Algo no me cuadra. Parece que convierte sólo el 0 de la izquierda y obvia los dos caracteres del campo de la tabla. De funcionar bien tendría que aparece en ambos un 1 en vez de ese 0. Eso sí: Todos los los códigos postales iguales o superiores a 10 ni los ha tocado.


Angel.Matilla 24-04-2018 19:42:55

Otra cosa, y perdón por el barullo de mensajes: Me valdría peferctamente al revés:
Código PHP:

SELECT CODIGONOMBRECPOSTAL
FROM POBLACION
WHERE SUBSTRING
(CPOSTAL FROM 1 FOR 2NOT IN (SELECT CAST(CODIGO AS VARCHAR(2))
FROM PROVINCIA WHERE CODIGO AND CODIGO 99ORDER BY CPOSTALNOMBRECODIGO 

Pero este query me saca todos los registros de la tabla (más de 58.000).

Casimiro Notevi 24-04-2018 20:28:48

La verdad es que no se entiende bien lo que pretendes, por eso te preguntaba antes:
Cita:

Empezado por casimiro notevi
¿exactamente qué quieres conseguir?


bucanero 25-04-2018 09:49:49

Hola a todos,


Cita:

Empezado por Angel.Matilla (Mensaje 525860)
Otra cosa, y perdón por el barullo de mensajes: Me valdría peferctamente al revés:
Código PHP:

SELECT CODIGONOMBRECPOSTAL
FROM POBLACION
WHERE SUBSTRING
(CPOSTAL FROM 1 FOR 2NOT IN (SELECT CAST(CODIGO AS VARCHAR(2))
FROM PROVINCIA WHERE CODIGO AND CODIGO 99ORDER BY CPOSTALNOMBRECODIGO 

Pero este query me saca todos los registros de la tabla (más de 58.000).

prueba con:
Código PHP:

SELECT CODIGONOMBRECPOSTAL
FROM POBLACION
WHERE SUBSTRING
(CPOSTAL FROM 1 FOR 2NOT IN (SELECT LPAD(CAST(CODIGO AS VARCHAR(2)), 2'0'FROM PROVINCIA WHERE CODIGO AND CODIGO 99ORDER BY CPOSTALNOMBRECODIGO 

Eso esta pasando por que al convertir un código de provincia de un solo dígito, ejemplo Barcelona si utilizas los dos primeros dígitos del código postal correspondería a '08' y el código numérico se queda solo como 8, al aplicar solamente CAST(CODIGO AS VARCHAR(2)) obtienes '8' que no es igual a '08' con el LPAD se soluciona

Un saludo

duilioisola 25-04-2018 10:27:07

Perdón, el ejemplo que di anteriormente no estaba del todo bien.
Debes concatenar el 0 al resultado del substring y no antes:
Me explico
  1. Primero obtenes los dos primeros dígitos del código postal. Eso lo obtienes mediante SUBSTRING.
  2. Luego le agregas un '0' delante, mediante la concatencacion.
  3. Finalmente conviertes esos tres dígitos ('0' + resultado de SUBSTRING) a integer mediante el CAST.
La idea es que si el SUBSTRING te devuelve "vacío", por lo menos haya un '0' para convertir.

Código SQL [-]
/* CAST('0'  + primeros dos dígitos del código postal AS INTEGER) */

SELECT CODIGO, NOMBRE, CPOSTAL, CAST('0' || SUBSTRING(CPOSTAL FROM 1 FOR 2) AS INTEGER)
FROM POBLACION
WHERE
CAST('0' || SUBSTRING(CPOSTAL FROM 1 FOR 2) AS INTEGER) NOT IN (SELECT CODIGO
                                                                FROM PROVINCIA
                                                                WHERE
                                                                CODIGO > 0 AND
                                                                CODIGO < 99)
ORDER BY CPOSTAL, NOMBRE, CODIGO

Casimiro Notevi 25-04-2018 10:42:18

Cita:

Empezado por duilioisola (Mensaje 525868)
Debes concatenar el 0 al resultado del substring y no antes:

Pequeño detalle, gran solución :)

Angel.Matilla 25-04-2018 18:19:30

Cita:

Empezado por Casimiro Notevi (Mensaje 525861)
La verdad es que no se entiende bien lo que pretendes, por eso te preguntaba antes:

Perdón por no haber contestado antes. Busco todas aquellas localidades que por error u omisión tengan mal puesto el código postal. En España estos van desde el 01xxx al 52xxx; eso lo que busco. Como las dos primeras posiciones coinciden con el código provincial, bsuco códigos postales que no coincidan con ese patrón.

Angel.Matilla 25-04-2018 18:22:02

Vale. Acabo de hacer sendas pruebas con los códigos propuestos por bucanero y duilioisola y, aparentemente, ambos funcionan correctamente. Muchísimas gracias a todos por vuestra ayuda. Ya sé que soy un pelín paliza. :o

Casimiro Notevi 25-04-2018 18:35:34

Cita:

Empezado por Angel.Matilla (Mensaje 525882)
Perdón por no haber contestado antes. Busco todas aquellas localidades que por error u omisión tengan mal puesto el código postal. En España estos van desde el 01xxx al 52xxx; eso lo que busco. Como las dos primeras posiciones coinciden con el código provincial, bsuco códigos postales que no coincidan con ese patrón.

Entonces, ¿el código de provincia debe ser siempre igual a los 2 primeros dígitos del código postal?

Angel.Matilla 25-04-2018 18:45:51

Cita:

Empezado por Casimiro Notevi (Mensaje 525884)
Entonces, ¿el código de provincia debe ser siempre igual a los 2 primeros dígitos del código postal?

En España sí. Las dos primeras posiciones del código postal indican la provincia por orden alfabético: 28 es Madrid, 33 Asturias (por Oviedo), 45 Toledo, etc.

Casimiro Notevi 25-04-2018 19:27:20

Cita:

Empezado por Angel.Matilla (Mensaje 525885)
En España sí. Las dos primeras posiciones del código postal indican la provincia por orden alfabético: 28 es Madrid, 33 Asturias (por Oviedo), 45 Toledo, etc.

Bien, aunque me refería a tus tablas provincia y poblacion.
Tienes en la tabla poblacion los campos codprv y cpostal, que se suponen que son el código de la provincia (enlaza con campo codigo en tabla provincia) y tienes el campo cpostal, entonces en la tabla poblacion, todos los cpostal deberán iniciar con los mismos valores que codprv, ¿es así?

Es que entonces puedes buscar diferencias entre esos campos, algo más o menos así:
Código SQL [-]
SELECT codprv, cpostal
FROM POBLACION
where ('0'||substring(cpostal from 1 for 2)) <> ('0'||substring(codprv from 1 for 2))

Código:

CODPRV CPOSTAL
13    00000
13    43518
13    15177
13    44155
13    36330


Angel.Matilla 26-04-2018 12:20:05

Cita:

Empezado por Casimiro Notevi (Mensaje 525887)
Bien, aunque me refería a tus tablas provincia y poblacion.
Tienes en la tabla poblacion los campos codprv y cpostal, que se suponen que son el código de la provincia (enlaza con campo codigo en tabla provincia) y tienes el campo cpostal, entonces en la tabla poblacion, todos los cpostal deberán iniciar con los mismos valores que codprv, ¿es así?

No. Si te fijas en las tablas que te envié es campo CodPrv está en casi todas las tablas.

En un principio la aplicación se pensó para poder acumular las bases de datos de distintas provincias y ese campo sirve para distinguir el origen de los datos; el probelma es que las bases de datos no estan conectadas y cada provincia tiene la suya propia. Por ejemplo:

Tanto en Ciudad Real (13) como en Toledo (45) pueden tener una misma población pero con distinto código. Digamos que en ambas provincias tienen grabado en el fichero de poblaciones a Toledo, pero en Ciudad Real tiene el código 2 y en Toledo el 1. Ese código está asociado en varias tablas (como puede ser la de personas), pero al acumular todas las bases de datos en una única necesito que viajen todos los datos para poder localizarlos, independientemente del origen de los mismos.

Sé que no es un buen sistema, que lo suyo sería una única base de datos conectada vía internet pero se resisten de una forma tremenda a "perder" el control de "sus" datos.

Angel.Matilla 26-04-2018 12:23:06

Hay tres tablas (bancos, provincias y países) que no tiene esa columna porque todas ellas son iguales en cualquier instalación. Por ejemplo: al margen de la provincia que gestione los datos, la entidad bancaria de código 0049 dentro de España siempre será el Banco de Santander o la provincia 28 siempre será Madrid.

Casimiro Notevi 26-04-2018 12:34:49

Gracias por la aclaración ^\||/

Angel.Matilla 26-04-2018 17:51:28

sin mayor probelma. Gracias a vosotros por vuestra inapreciable ayuda.


La franja horaria es GMT +2. Ahora son las 13:52:49.

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