Ordenar campo texto como numérico.
Tenho uma tabela que armazena endereços IP e preciso ordená-las pelos mesmos. Entretanto isso causa um grande problema, pois os valores ficam ordenados à partir do código alfabético do caracter e não do valore real, por exemplo:
172.16.0.10 <<======
172.16.0.100
172.16.0.101
172.16.0.102
172.16.0.11 <<======
172.16.0.110
172.16.0.111
Há alguma maneira de efetuar esta ordem de maneira coerente ? Tentei utilizar ORDER BY CAST(IP AS Numeric) mas não funciona devido aos pontos. Tentei também desmontar o IP utilizando SUBSTRING e CHARINDEX mas ficou muito complicado por causa tmb dos pontos.
172.16.0.10 <<======
172.16.0.100
172.16.0.101
172.16.0.102
172.16.0.11 <<======
172.16.0.110
172.16.0.111
Há alguma maneira de efetuar esta ordem de maneira coerente ? Tentei utilizar ORDER BY CAST(IP AS Numeric) mas não funciona devido aos pontos. Tentei também desmontar o IP utilizando SUBSTRING e CHARINDEX mas ficou muito complicado por causa tmb dos pontos.
Rc.salvador
Curtidas 0
Respostas
Gandalf.nho
02/05/2005
Enquanto permanecer como texto ele irá ordenar alfabeticamente e não numericamente, a menos que todos os IPs tenham o mesmo tamanho e os pontos nos mesmos lugares (o que não dá)
GOSTEI 0
Tinorj
02/05/2005
Uma solução seria armazenar cada numero separado e fazer um campo calculado exibindo o IP já concatenado com os pontos, mas não sei qual seria esse custo para sua situação.
Abaixo segue um exemplo.
Abaixo segue um exemplo.
use Northwind GO if exists (select * from dbo.sysobjects where id = object_id(N´[dbo].[IPs]´) and OBJECTPROPERTY(id, N´IsUserTable´) = 1) drop table [dbo].[IPs] GO CREATE TABLE [dbo].[IPs] ( [PARTE1] [int] NULL , [PARTE2] [int] NULL , [PARTE3] [int] NULL , [PARTE4] [int] NULL , [IP] AS (CONVERT(varchar(3),[PARTE1]) + ´.´ + CONVERT(varchar(3),[PARTE2]) + ´.´ + CONVERT(varchar(3),[PARTE3]) + ´.´ + CONVERT(varchar(3),[PARTE4])) ) ON [PRIMARY] GO ALTER TABLE [dbo].[IPs] ADD CONSTRAINT [DF_IPs_PARTE1] DEFAULT (0) FOR [PARTE1], CONSTRAINT [DF_IPs_PARTE2] DEFAULT (0) FOR [PARTE2], CONSTRAINT [DF_IPs_PARTE3] DEFAULT (0) FOR [PARTE3], CONSTRAINT [DF_IPs_PARTE4] DEFAULT (0) FOR [PARTE4], CONSTRAINT [CK_IP_PARTE1] CHECK ([PARTE1] >= 0 and [PARTE1] < 255), CONSTRAINT [CK_IP_PARTE2] CHECK ([PARTE2] >= 0 and [PARTE2] < 255), CONSTRAINT [CK_IP_PARTE3] CHECK ([PARTE3] >= 0 and [PARTE3] < 255), CONSTRAINT [CK_IP_PARTE4] CHECK ([PARTE4] >= 0 and [PARTE4] < 255) GO GO INSERT INTO IPs VALUES (172,16,0,10) INSERT INTO IPs VALUES (172,16,0,100) INSERT INTO IPs VALUES (172,16,0,101) INSERT INTO IPs VALUES (172,16,0,102) INSERT INTO IPs VALUES (172,16,0,11) INSERT INTO IPs VALUES (172,16,0,110) INSERT INTO IPs VALUES (172,16,0,111) GO SELECT IP FROM IPs ORDER BY PARTE1, PARTE2, PARTE3, PARTE4
GOSTEI 0
Psergio.p
02/05/2005
Minha sugestão é a seguinte:
Criar uma UDF para retornar as partes do IP, veja abaixo o exemplo:
CREATE FUNCTION UDF_GETIP(@ENDERECO_IP VARCHAR(15),@PARTE INT)
RETURNS INT
AS
BEGIN
DECLARE @PARTE01 INT
DECLARE @PARTE02 INT
DECLARE @PARTE03 INT
DECLARE @PARTE04 INT
DECLARE @POSICAO INT
SET @POSICAO = CHARINDEX(´.´,@ENDERECO_IP)
SET @PARTE01 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
SET @ENDERECO_IP = SUBSTRING(@ENDERECO_IP,@POSICAO + 1, LEN(@ENDERECO_IP))
SET @POSICAO = CHARINDEX(´.´,@ENDERECO_IP)
SET @PARTE02 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
SET @ENDERECO_IP = SUBSTRING(@ENDERECO_IP,@POSICAO + 1, LEN(@ENDERECO_IP))
SET @POSICAO = CHARINDEX(´.´,@ENDERECO_IP)
SET @PARTE03 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
SET @ENDERECO_IP = SUBSTRING(@ENDERECO_IP,@POSICAO + 1, LEN(@ENDERECO_IP))
SET @PARTE04 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
IF @PARTE = 1 BEGIN
RETURN(@PARTE01)
END
IF @PARTE = 2 BEGIN
RETURN(@PARTE02)
END
IF @PARTE = 3 BEGIN
RETURN(@PARTE03)
END
IF @PARTE = 4 BEGIN
RETURN(@PARTE04)
END
RETURN 0
END
Depois veja como usar a função e order os valores:
SELECT IP FROM(
SELECT *,DBO.UDF_GETIP(IP,1) AS IP1,DBO.UDF_GETIP(IP,2) AS IP2,DBO.UDF_GETIP(IP,3) AS IP3,
DBO.UDF_GETIP(IP,4) AS IP4 FROM EnderecoIP) AS SQ
ORDER BY IP1,IP2,IP3,IP4
Espero que ajude, me dá um feedback depois!
[]
Paulo
Criar uma UDF para retornar as partes do IP, veja abaixo o exemplo:
CREATE FUNCTION UDF_GETIP(@ENDERECO_IP VARCHAR(15),@PARTE INT)
RETURNS INT
AS
BEGIN
DECLARE @PARTE01 INT
DECLARE @PARTE02 INT
DECLARE @PARTE03 INT
DECLARE @PARTE04 INT
DECLARE @POSICAO INT
SET @POSICAO = CHARINDEX(´.´,@ENDERECO_IP)
SET @PARTE01 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
SET @ENDERECO_IP = SUBSTRING(@ENDERECO_IP,@POSICAO + 1, LEN(@ENDERECO_IP))
SET @POSICAO = CHARINDEX(´.´,@ENDERECO_IP)
SET @PARTE02 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
SET @ENDERECO_IP = SUBSTRING(@ENDERECO_IP,@POSICAO + 1, LEN(@ENDERECO_IP))
SET @POSICAO = CHARINDEX(´.´,@ENDERECO_IP)
SET @PARTE03 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
SET @ENDERECO_IP = SUBSTRING(@ENDERECO_IP,@POSICAO + 1, LEN(@ENDERECO_IP))
SET @PARTE04 = SUBSTRING(@ENDERECO_IP,1,@POSICAO - 1)
IF @PARTE = 1 BEGIN
RETURN(@PARTE01)
END
IF @PARTE = 2 BEGIN
RETURN(@PARTE02)
END
IF @PARTE = 3 BEGIN
RETURN(@PARTE03)
END
IF @PARTE = 4 BEGIN
RETURN(@PARTE04)
END
RETURN 0
END
Depois veja como usar a função e order os valores:
SELECT IP FROM(
SELECT *,DBO.UDF_GETIP(IP,1) AS IP1,DBO.UDF_GETIP(IP,2) AS IP2,DBO.UDF_GETIP(IP,3) AS IP3,
DBO.UDF_GETIP(IP,4) AS IP4 FROM EnderecoIP) AS SQ
ORDER BY IP1,IP2,IP3,IP4
Espero que ajude, me dá um feedback depois!
[]
Paulo
GOSTEI 0