Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
jshepler
Yak Posting Veteran
60 Posts |
Posted - 2003-09-20 : 13:45:19
|
| [code]CREATE TABLE #T(IP NVARCHAR(15), Usage NVARCHAR(20))INSERT INTO #TSELECT '192.168.2.0', 'Network Address' UNION ALLSELECT '192.168.2.1', 'Unallocated' UNION ALLSELECT '192.168.2.2', 'Unallocated' UNION ALLSELECT '192.168.2.3', 'Unallocated' UNION ALLSELECT '192.168.2.4', 'Unallocated' UNION ALLSELECT '192.168.2.5', 'Web Site' UNION ALLSELECT '192.168.2.6', 'Web Site' UNION ALLSELECT '192.168.2.7', 'Web Site' UNION ALLSELECT '192.168.2.8', 'Web Site' UNION ALLSELECT '192.168.2.9', 'Web Site' UNION ALLSELECT '192.168.2.10', 'Unallocated' UNION ALLSELECT '192.168.2.11', 'Unallocated' UNION ALLSELECT '192.168.2.12', 'Unallocated' UNION ALLSELECT '192.168.2.13', 'Server' UNION ALLSELECT '192.168.2.14', 'Server' UNION ALLSELECT '192.168.2.15', 'Broadcast Address'[/code]I need the results to look like:[code]BegIP EndIP Usage-------------------------------------------------192.168.2.0 192.168.2.0 Network Address192.168.2.1 192.168.2.4 Unallocated192.168.2.5 192.168.2.10 Web Site192.168.2.11 192.168.2.12 Unallocated192.168.2.13 192.168.2.14 Server192.168.2.15 192.168.2.15 Broadcast Address[/code]I cannot figure out how to get this result and would appreciate any help.Also, MAX() says that the text "***.***.***.9" is greater than "***.***.***.10". I understand why that is, but how can I have it sort by number. To make it a little bit harder, the range of IP address can be more than 256 address and needs to take that into account. For example, the range could be 192.168.8.3 - 192.168.12.32 and it needs to show that 192.168.9.* is less than 192.168.10.*.I did try it by having a seperate field for each octet, but when I tried to use the MIN() function to get the low end of a range, it would return (using the last example) 192.168.8.0. This was using something like SELECT MIN(Oct3) + '.' + MIN(Oct4) grouped by usage. Well, MIN(Oct3) returned the 8 like it was supposed to, but since 192.168.9.0 is within the range of address, MIN(Oct4) returned 0.So, I used MIN((Oct3 * 256) + Oct4) and I got the correct value, but I couldn't figure out how to return the IP instead of the calculated number.Any help would be greatly appreciated. |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-09-20 : 16:55:01
|
| clue 1: break each field into an octet as you mentioned, make sure they are numeric datatypes.clue 2:then, check out my article here at SQLTeam on runs and streaks. The answer is really easy if you apply the technique from the article. Here's the article: http://www.sqlteam.com/item.asp?ItemID=12654clue 3: You had a good idea: Calculate oct3 * 256 + oct4 and deal with that value during the process taking of the MIN() and the MAX() of a range of values. To transalte that value BACK: Oct3 = convert(int, value / 256) and Oct4 = value % 256.if no one can figure it out from the above 3 clues, let me know ! it's not easy, but the basic info should be there !- Jeff |
 |
|
|
Stoad
Freaky Yak Linguist
1983 Posts |
Posted - 2003-09-21 : 06:35:45
|
create table h (n varchar(8), m int)insert into hselect 'a', 1 union allselect 'a', 3 union allselect 'a', 4 union allselect 'a', 4 union allselect 'a', 5 union allselect 'a', 6 union allselect 'a', 6 union allselect 'a', 6 union allselect 'a', 8 union allselect 'a', 9 union allselect 'a', 12 union allselect 'b', 1 union allselect 'b', 1 union allselect 'b', 2 union allselect 'b', 2 union allselect 'b', 5select n, min(m) m1, max(m) m2 from(select n, m,m-(select count(distinct m) from h hh where hh.n=h.n and hh.m<h.m) kkfrom h) rgroup by n, kkproduces:n m1 m2 -------- ----------- ----------- a 1 1a 3 6a 8 9a 12 12b 1 2b 5 5 Jeff, don't you mind to post here how it appears in your approach? |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-09-22 : 09:05:48
|
OK, here you go:CREATE TABLE #T(Oct3 int, Oct4 int, Usage NVARCHAR(20))GOINSERT INTO #T (oct3, oct4, Usage)SELECT 2,0, 'Network Address' UNION ALLSELECT 2,1, 'Unallocated' UNION ALLSELECT 2,2, 'Unallocated' UNION ALLSELECT 2,3, 'Unallocated' UNION ALLSELECT 2,4, 'Unallocated' UNION ALLSELECT 2,5, 'Web Site' UNION ALLSELECT 2,6, 'Web Site' UNION ALLSELECT 2,7, 'Web Site' UNION ALLSELECT 2,8, 'Web Site' UNION ALLSELECT 2,9, 'Web Site' UNION ALLSELECT 2,10, 'Unallocated' UNION ALLSELECT 2,11, 'Unallocated' UNION ALLSELECT 2,12, 'Unallocated' UNION ALLSELECT 2,13, 'Server' UNION ALLSELECT 2,14, 'Server' UNION ALLSELECT 2,15, 'Broadcast Address' UNION ALLSELECT 2,16, 'Another' UNION ALLSELECT 3,1,'Another' UNION ALLSELECT 3,2,'Another' UNION ALLSELECT 3,6,'One More' UNION ALLSELECT 3,10,'One More'GOselect Usage, '192.168.' + convert(varchar, min(tmp) / 256) + '.' + convert(varchar, min(tmp) % 256) as FromIP, '192.168.' + convert(varchar,max(tmp) / 256) + '.' + convert(varchar, max(tmp) % 256) as ToIP, count(*) as [# of Addresses]from( select a.*, (select count(*) from #t b where ((b.Oct3 < a.Oct3) or (b.Oct3 = A.Oct3 and b.Oct4 <= a.oct4)) and a.Usage<> B.Usage) as RunGroupfrom (select #t.*, oct3 * 256 + oct4 as tmp from #t) a) agroup by usage, runGroupGODROP TABLE #t I admit this isn't easy stuff, but hopefully it makes SOME sense. let me know if anyone needs it dissected, but the 3 clues in my first post should explain most of it.also, note I added some more sample data, and normalized it a little (as discussed in the previous posts) .... - Jeff |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-09-22 : 09:43:59
|
quote: Originally posted by jsheplerBegIP EndIP Usage-------------------------------------------------192.168.2.0 192.168.2.0 Network Address192.168.2.1 192.168.2.4 Unallocated192.168.2.5 192.168.2.10 Web Site192.168.2.11 192.168.2.12 Unallocated192.168.2.13 192.168.2.14 Server192.168.2.15 192.168.2.15 Broadcast Address
Shouldn't Web site be 5-9? Unallocated be 10-12?If not, I'm missing something....Brett8-)SELECT @@POST=NewId()That's correct! It's an AlphaNumeric! |
 |
|
|
Stoad
Freaky Yak Linguist
1983 Posts |
Posted - 2003-09-22 : 09:59:41
|
| Jeff:Great!But I meant to see your approahon my intentionally simplified data. |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-09-22 : 10:07:13
|
| Jeff,That's my point...his result set is different...unless s/he made a mistake in the result set to be returned...Great stuff though...another one for the SQL tool box...Brett8-)SELECT @@POST=NewId()That's correct! It's an AlphaNumeric! |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-09-22 : 10:10:54
|
| Stoad -- your sample data makes no sense at all. the technique is for recognizing runs of consective values in your data, which requires a unique and orderable key in the table. Your table has no key, and I see no concept of ordering in your data.What result should be returned with your data? what does it represent?To recognize streaks in your data, the column you are "grouping" for the sake of the streak should NOT be involved in the PK of the table, as well, for obvious reasons.Check out the article.- Jeff |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-09-22 : 10:12:15
|
| Jeff,That's my point...his result set is different...unless s/he made a mistake in the result set to be returned...Great stuff though...another one for the SQL tool box...Brett8-)SELECT @@POST=NewId()That's correct! It's an AlphaNumeric! |
 |
|
|
Stoad
Freaky Yak Linguist
1983 Posts |
Posted - 2003-09-22 : 14:05:25
|
>your sample data makes no sense at all. the technique is for>recognizing runs of consective values in your data, which>requires a unique and orderable key in the table. Your>table has no key, and I see no concept of ordering in>your data.My query does exactly the same thing - recognizes runs of consectivevalues in field m in each group of n field values.select n, min(m) m1, max(m) m2 from(select n, m,m-(select count(distinct m) from h hh where hh.n=h.n and hh.m<h.m) kkfrom h) rgroup by n, kk this is result table h of above query ------------- ------------------n m n m1 m2-------- ---- ---- ---- ----a 1 a 1 1a 3 a 3 6a 4 a 8 9a 4 a 12 12a 5 b 1 2a 6 b 5 5a 6 ------------------a 6a 8a 9a 12b 1b 1b 2b 2b 5------------ |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-09-22 : 14:16:35
|
| Stoad -- yours is actually 100% different.Again, I will suggest that you read the article.Your query looks for NUMERICAL gaps in the "m" column and displays results for which there are no gaps.Mine has nothing to do with gaps in the data. Note in the article there are NO numbers of any kind in the sample data, and it has nothing to do with whether or not the games occur on consective days or weeks apart. It has to do with ordering rows in a table by a column (or two), and after doing that, seeing how many consective values in ANOTHER column there are -- with or without gaps.My alogorithm answers a different question and is for a different type of data other than what you are showing. Does this make sense?This isn't to suggest that my technique is the ideal solution for this problem, or that your solution or techinique is a bad one, just that they are completely DIFFERENT concepts.- Jeff |
 |
|
|
Stoad
Freaky Yak Linguist
1983 Posts |
Posted - 2003-09-22 : 15:07:58
|
| OK, Jeff. Thank you. I've already read your article on last Sundaybut very fluently and carelessly. Seems it is deserved my re-reading. |
 |
|
|
Stoad
Freaky Yak Linguist
1983 Posts |
Posted - 2003-09-22 : 16:15:42
|
Now I really see the difference between two approachs.Jeff, I changed a bit your test input data as followsCREATE TABLE #T(Oct3 int, Oct4 int, Usage NVARCHAR(20))GOINSERT INTO #T (oct3, oct4, Usage)SELECT 2,1, 'Unallocated' UNION ALLSELECT 2,2, 'Unallocated' UNION ALLSELECT 2,3, 'Unallocated' UNION ALLSELECT 2,6, 'Unallocated' UNION ALLSELECT 2,10, 'Unallocated' UNION ALLSELECT 2,11, 'Unallocated' UNION ALLSELECT 2,255, 'Unallocated' UNION ALLSELECT 3,0, 'Unallocated'GOand your query produced this result:Usage FromIP ToIP # of Addresses -------------- -------------- ------------- -------------- Unallocated 192.168.2.1 192.168.3.0 8 In fact my query in my first reply (I deleted it for thesake of graz's DB space, counting it as inappropriate)produced the same result.To be honest I think it should be:Usage FromIP ToIP-------------- -------------- ------------- Unallocated 192.168.2.1 192.168.2.3Unallocated 192.168.2.6 192.168.2.6Unallocated 192.168.2.10 192.168.2.11Unallocated 192.168.2.255 192.168.3.0 |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-09-22 : 17:38:40
|
| absolutely ... depends what he needs and what his data looks like.- Jeff |
 |
|
|
jshepler
Yak Posting Veteran
60 Posts |
Posted - 2003-09-23 : 09:16:00
|
quote: Originally posted by X002548
quote: Originally posted by jsheplerBegIP EndIP Usage-------------------------------------------------192.168.2.0 192.168.2.0 Network Address192.168.2.1 192.168.2.4 Unallocated192.168.2.5 192.168.2.10 Web Site192.168.2.11 192.168.2.12 Unallocated192.168.2.13 192.168.2.14 Server192.168.2.15 192.168.2.15 Broadcast Address
Shouldn't Web site be 5-9? Unallocated be 10-12?If not, I'm missing something....Brett8-)SELECT @@POST=NewId()That's correct! It's an AlphaNumeric!
Sorry, you are correct in regards to what I posted as the source. I mistakenly put .10 as unallocated when I wanted it as Web Site so that when testing, .10 would come after .9 (assuming still using text-based sort).The sample data isn't really being used, just some data I made up for the post. We actually have various Class C subnets - all numbered differently (207.40.127.*, 209.115.44.*, etc.). Have to keep the 3rd octet in the mix because we do have a block of IPs that span 16 "class C subnets". So, I can't hardcode the first two octets.Thanks for the tips Jeff, Brett, and Stoad. I appreciate the replies. |
 |
|
|
joseph
Starting Member
10 Posts |
Posted - 2003-09-23 : 12:49:50
|
| here you go :select Usage,BegIP=replace(replace(BegIP,'.0','.'),'.0','.'),EndIP=replace(replace(EndIP,'.0','.'),'.0','.')from(select Usage,BegIP=min(newip),EndIP=max(newip)from (select newip=right('000'+octet1,3)+'.'+right('000'+octet2,3)+'.'+right('000'+octet3,3)+'.'+right('000'+octet4,3),Usagefrom(select octet1,octet2,octet3=substring(ip,1,charindex('.',ip)-1),octet4=substring(ip,charindex('.',ip)+1,len(ip)-charindex(ip,'.')),Usagefrom(select ip=substring(ip,charindex('.',ip)+1,len(ip)-charindex(ip,'.')),octet2=substring(ip,1,charindex('.',ip)-1),octet1,Usagefrom(select ip=substring(ip,charindex('.',ip)+1,len(ip)-charindex(ip,'.')) ,octet1=substring(ip,1,charindex('.',ip)-1),Usage from #T) firstlevel) secndlevel)thirdlevel)forthlevelgroup by Usage)lastlevelignore lastlevel if the result is acceptable for you(192.168.002.000,etc)you can use more nested replace to get ride of extra zero.Thanks stoad for learnig me new thing .I also appricate Jeff because . he learned me many new idea in sql.I owe him |
 |
|
|
jshepler
Yak Posting Veteran
60 Posts |
Posted - 2003-09-23 : 13:08:04
|
quote: Originally posted by jsmith8858 absolutely ... depends what he needs and what his data looks like.- Jeff
There are no gaps in the data. There is a row for every IP in a particular network - 256 rows per network. One of the uses of this database is to be able to get the next unused IP for a particular usage. The usage interface just needs to list the current usages and accept input to change a usage for a range of IPs.This part of the database is made up of 3 tables:Networks (NetworkID int, Network nvarchar(11))IPs (IPID int, NetworkID int, IP tinyint, IPUsageID tinyint, ...)IPUsages (IPUsageID tinyint, IPUsage nvarchar(20))I made a view to help with this part:CREATE VIEW _IPUsageasSELECT Network + '.' + CAST(IP AS VARCHAR) AS 'IP', ISNULL(IPUsage, 'Unallocated') AS 'Usage', SubnetID, CAST(RIGHT(Network, CHARINDEX('.', REVERSE(Network)) - 1) AS TinyINT) * 256 + IP AS 'Hash'FROM IPs INNER JOIN Networks ON IPs.NetworkID = Networks.NetworkID LEFT JOIN IPUsages ON IPs.IPUsageID = IPUsages.IPUsageIDNo problem to make the 3 octets in the Networks table 3 different TinyINT columns. I'm going to read your article on my lunch and see if I can figure out how to apply your technique to my query.Thanks/Jeff |
 |
|
|
jshepler
Yak Posting Veteran
60 Posts |
Posted - 2003-09-23 : 13:56:43
|
Here's what I came up with:select Beg.IP as BegIP, [End].IP as EndIP, Beg.Usagefrom (select min(hash) as MinHash, max(hash) as MaxHash, usage from (select Hash, Usage, (select count(*) from _IPUsage IU1 where IU1.Usage <> IU2.Usage and IU1.Hash <= IU2.Hash and ) as RunGroup from _IPUsage IU2 ) a group by Usage, RunGroup) IUINNER JOIN _IPUsage Beg ON IU.MinHash = Beg.HashINNER JOIN _IPUsage [End] ON IU.MaxHash = [End].Hashorder by IU.MinHash But I'm not happy with it. It takes 4 seconds to return a few rows. I'm assuming because I'm using a view and the cost is goin through the roof. However, I think I got the idea (I got the results I wanted) and I'm going to try it using numerical fields for the octets instead of a string. Then I can skip the view. Should be much faster./Jeff |
 |
|
|
jsmith8858
Dr. Cross Join
7423 Posts |
Posted - 2003-09-23 : 14:18:58
|
quote: However, I think I got the idea (I got the results I wanted) and I'm going to try it using numerical fields for the octets instead of a string. Then I can skip the view. Should be much faster.
YES! should be much faster. good luck.Again, if there are NO gaps in the IP addresses you are working with, you might be better off using a different algorithm similiar to Stoads.- Jeff |
 |
|
|
yousef
Starting Member
1 Post |
Posted - 2003-09-23 : 14:31:09
|
| jsheplerDo you try my reply?tell me does that work?yousef |
 |
|
|
jshepler
Yak Posting Veteran
60 Posts |
Posted - 2003-09-23 : 18:05:31
|
yousef, Sorry, I don't see your reply to try out.Jeff, I have a question about your method. In you games example, let's say that you want to track ties and the ties are represented by NULLs. How would you change your method to handle that. I ask because I think I have it working like it should, but I use NULL in the Usage column for IPs that are unallocated. For those rows that have NULLs, the "RunGroup" value comes out 0.Here's where I'm at with this:select cast(oct1 as varchar) + '.' + cast(oct2 as varchar) + '.' + cast(min(hash) / 256 as varchar) + '.' + cast(min(hash) % 256 as varchar) as 'BegIP', cast(oct1 as varchar) + '.' + cast(oct2 as varchar) + '.' + cast(max(hash) / 256 as varchar) + '.' + cast(max(hash) % 256 as varchar) as 'EndIP', Usagefrom (select Oct1, Oct2, (oct3 * 256) + IP as 'Hash', ISNULL(IPUsage, 'Unallocated') as Usage, (select count(*) from IPs I1 INNER JOIN Networks N1 ON I1.NetworkID = N1.NetworkID LEFT JOIN IPUsages IPU1 ON I1.IPUsageID = IPU1.IPUsageID where I1.IPUsageID <> I2.IPUsageID AND (N1.Oct3 * 256) + I1.IP <= (N2.Oct3 * 256) + I2.IP and subnetid = 204 ) as RunGroup from IPs I2 INNER JOIN Networks N2 ON I2.NetworkID = N2.NetworkID LEFT JOIN IPUsages IPU2 ON I2.IPUsageID = IPU2.IPUsageID where subnetid = 204 ) aGroup By RunGroup, usage, Oct1, Oct2ORDER BY min(hash) Ignore subnetid. A value will be passed, not hardcoded. This is just testing through QA.IPUsageID is NULL for the IPs that are unallocated. Granted, I could just make an entry in the IPUSages table for Unallocated and this query will probably work like it's supposed to, but I'm rather curious why it isn't counting the rows that have NULL in that column (I am using a LEFT JOIN, so they should all be there)./Jeff |
 |
|
|
Next Page
|
|
|
|
|