By Frank Kalis
Nun, grundsätzlich würde ich wahrscheinlich eher zu einem anderen Datentyp als VARCHAR tendieren, um IP Adressen zu speichern, aber dennoch fand ich diese "Koproduktion" der beiden SQL Server MVP's Steve Kass und Itzik Ben-Gan in der englischen Newsgroup sehr interessant. Folgender Lösungsansatz kam von Steve Kass
create table T ( ipAdd varchar(15) ) insert into T select rtrim(abs(binary_checksum(newid()))%256) + '.' + rtrim(abs(binary_checksum(newid()))%256) + '.' + rtrim(abs(binary_checksum(newid()))%256) + '.' + rtrim(abs(binary_checksum(newid()))%256) from Northwind..Orders go -- sort by ipAdd select ipAdd from T order by 0 + parsename(ipAdd,4), 0 + parsename(ipAdd,3), 0 + parsename(ipAdd,2), 0 + parsename(ipAdd,1) go
So, ausgehend von dieser Beispieltabelle T kam dann folgender Vorschlag von Itzik Ben-Gan:
CREATE VIEW Patterns AS SELECT REPLICATE('_',N1.n) + '.' + REPLICATE('_',N2.n) + '.' + REPLICATE('_',N3.n) + '.' + REPLICATE('_',N4.n) AS pattern, 1 AS s1, N1.n AS l1, N1.n+2 AS s2, N2.n AS l2, N1.n+N2.n+3 AS s3, N3.n AS l3, N1.n+N2.n+N3.n+4 AS s4, N4.n AS l4 FROM Nums AS N1, Nums AS N2, Nums AS N3, Nums AS N4 WHERE N1.n <= 3 AND N2.n <= 3 AND N3.n <= 3 AND N4.n <= 3 GO SELECT T.* FROM T JOIN Patterns ON ipAdd LIKE pattern ORDER BY CAST(SUBSTRING(ipAdd,s1,l1) AS TINYINT), CAST(SUBSTRING(ipAdd,s2,l2) AS TINYINT), CAST(SUBSTRING(ipAdd,s3,l3) AS TINYINT), CAST(SUBSTRING(ipAdd,s4,l4) AS TINYINT) GO
Ben-Gan verwendet eine nummerische Hilfstabelle, die in vielen Fällen extrem hilfreich sein kann, und die man mit:
SELECT TOP 1000 n = IDENTITY(INT) INTO Nums FROM Sysobjects S1 CROSS JOIN Sysobjects S2
relativ leicht erstellen kann. Zum Schluß kam noch einmal Steve Kass mit einer UDF basierten Lösung:
create function ipVal ( @ipAdd varchar(15) ) returns bigint as begin declare @a varchar(3), @b varchar(3), @c varchar(3), @d varchar(3) set @ipAdd = replace(@ipAdd,'.',space(1)) exec master..xp_sscanf @ipAdd, '%s%s%s%s', @a output, @b output, @c output, @d output return 256.*(256.*(256.*@a + @b)+ @c) + @d end GO
Die Ergebnismenge ist in allen drei Lösungen identisch und sieht verkürzt so aus:
ipAdd --------------- 0.29.139.218 0.42.28.216 0.112.240.205 1.63.169.105 1.159.167.72 2.168.143.230 3.50.2.153 3.53.44.168 3.95.215.255 3.108.33.169 3.146.81.33 3.168.194.74 3.239.97.179 4.14.61.195 4.81.148.233 4.91.186.46 4.131.70.150 4.138.171.124 4.244.58.66 5.40.88.33 5.61.160.216 5.72.228.141 5.121.171.82 5.136.210.214 5.194.153.107 5.223.170.8 6.14.82.89 6.211.186.133 7.141.188.164 8.120.148.128 8.148.94.165 9.115.251.14 9.173.205.139 9.173.218.157 ... ...