crucial_paradigm
asked on
MYSQL Group together query
Hi Everyone,
I am trying to put together a query that does the following:
I have a table with 512 entries in it (initially, this will increase with records at we add to it)
This table has columns id, ip_address, in_use where (id is auto_incrementing and primary) and in_use is bool true / false.
Basically I have a list of addresses in this (like I said initially it's got 512)
I need to ask mysql to return rows not in use, but group them together by a set number (ie I need 11 free addresses),
However, this system will have rows marked false on the in_use col right next to others with true.
I need a way to grab a set amount of IP's the id being broken sequentially... example
ids => in_use
1 => false
2 => false
3 => false
4 => false
5 => false
6 => false
7 => false
8 => false
9 => true
10 => true
11 => false
12 => false
13 => false
14 => false
15 => false
16 => false
17 => false
18 => false
19 => false
20 => false
21 => false
22 => false
23 => false
Now if I query for 11 free addresses, closest to the top, it will bring back the list of id's 1 to 12 skipping over 9, this won't work for what I am trying to do :(
What I would like it to do is realize that 9 is in use so cannot use that, thus cannot make a sequential group and pick from 11 to 22... as that is the next available sequential set.
Is there any way to structure a query for this? Is it even possible in MySQL?
Your help is kindly appreciated, Karl.
I am trying to put together a query that does the following:
I have a table with 512 entries in it (initially, this will increase with records at we add to it)
This table has columns id, ip_address, in_use where (id is auto_incrementing and primary) and in_use is bool true / false.
Basically I have a list of addresses in this (like I said initially it's got 512)
I need to ask mysql to return rows not in use, but group them together by a set number (ie I need 11 free addresses),
However, this system will have rows marked false on the in_use col right next to others with true.
I need a way to grab a set amount of IP's the id being broken sequentially... example
ids => in_use
1 => false
2 => false
3 => false
4 => false
5 => false
6 => false
7 => false
8 => false
9 => true
10 => true
11 => false
12 => false
13 => false
14 => false
15 => false
16 => false
17 => false
18 => false
19 => false
20 => false
21 => false
22 => false
23 => false
Now if I query for 11 free addresses, closest to the top, it will bring back the list of id's 1 to 12 skipping over 9, this won't work for what I am trying to do :(
What I would like it to do is realize that 9 is in use so cannot use that, thus cannot make a sequential group and pick from 11 to 22... as that is the next available sequential set.
Is there any way to structure a query for this? Is it even possible in MySQL?
Your help is kindly appreciated, Karl.
ASKER
Thanks Aaron!
I hope to see some type of demonstration of this soon, I am a bit baffled by your terminology so I will await your thoughts
I am doing this currently in the application level, but practically dropping a few thousand rows into array returns is not a good idea....
I look forward to hearing from you!
--Karl.
I hope to see some type of demonstration of this soon, I am a bit baffled by your terminology so I will await your thoughts
I am doing this currently in the application level, but practically dropping a few thousand rows into array returns is not a good idea....
I look forward to hearing from you!
--Karl.
SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
If you'll be getting more queries than updates, you might want to consider a caching mechanism:
1. Add column for tracking number of not in use IP addresses from current record until the next IP address not in use. For example:
2. Then, when marking a record with ID x not in use:
Essentially, you would be adjusting the cached count for records with affected counts.
3. When marking a record with ID x as in use:
4. A new record will just have 0 for contiguous_unused if in_use and 1 otherwise.
5. Selecting first set of 11 contiguous records:
This is a rough algorithm. Of course you will have to catch cases when last used or next used record is not existent (start or end of table) and optimize for mass inserts/updates.
Just a possibility.
1. Add column for tracking number of not in use IP addresses from current record until the next IP address not in use. For example:
id in_use contiguous_unused
1 true 1
2 false 0
3 true 1
4 true 2
5 false 0
2. Then, when marking a record with ID x not in use:
# Get first used IP address after current record with ID x.
next_used_id : SELECT MIN(id) FROM ip_addresses WHERE in_use IS TRUE AND id > x;
# Get contiguous_unused for current record.
current_contiguous_unused : SELECT COUNT(*) + 1 FROM ip_addresses WHERE in_use IS FALSE and id > x and id < next_used_id;
# Set contiguous_unused of current record.
UPDATE ip_addresses SET contiguous_unused = current_contiguous_unused WHERE id = x;
# Get last used IP address before current record with ID x.
last_used_id : SELECT MAX(id) FROM ip_addresses WHERE in_use IS TRUE AND id < x;
# Increment contiguous_unused by current_contiguous_unused for all records after last_used_id until previous record.
UPDATE ip_addresses SET contiguous_unused = contiguous_unused + current_contiguous_unused WHERE id > last_used_id AND id < x;
Essentially, you would be adjusting the cached count for records with affected counts.
3. When marking a record with ID x as in use:
# Get last used IP address before current record with ID x.
last_used_id : SELECT MAX(id) FROM ip_addresses WHERE in_use IS TRUE AND id < x;
# Set contiguous_unused of current record.
UPDATE ip_addresses SET contiguous_unused = 0 WHERE id = x;
# Decrement contiguous_unused by 1 for all records after last_used_id until previous record.
UPDATE ip_addresses SET contiguous_unused = contiguous_unused - 1 WHERE id > last_used_id AND id < x;
4. A new record will just have 0 for contiguous_unused if in_use and 1 otherwise.
5. Selecting first set of 11 contiguous records:
SELECT MIN(id) FROM ip_addresses WHERE contiguous_unused > 11;
This is a rough algorithm. Of course you will have to catch cases when last used or next used record is not existent (start or end of table) and optimize for mass inserts/updates.
Just a possibility.
Correction
5. Selecting first set of 11 contiguous records:
You can have flexible queries with this too, if you want to get the smallest unused range or even middle depending on your method for space optimization.
5. Selecting first set of 11 contiguous records:
SELECT MIN(id) FROM ip_addresses WHERE contiguous_unused >= 11;
You can have flexible queries with this too, if you want to get the smallest unused range or even middle depending on your method for space optimization.
ASKER
Thank you all for your replies,
Because of this I have now been able to form my database table and use it correctly!
--Karl
Because of this I have now been able to form my database table and use it correctly!
--Karl
If you add a rowcount column to the query output and then take the last part of the ip and subtract the rownumber, that should give you a constant number for contiguous ip addresses. Group by that column and add a count to see contiguous blocks. Change the ip to max(ip), ad a min(ip) and you should get start and end and counts of all the blocks. I won't be back at a PC until tomorrow to test all this but I think I will work and someone may be able to write it up before then ifyou can't figure it out.