IP address numbers in MySQL subquery

Posted by Iain Collins on Stack Overflow See other posts from Stack Overflow or by Iain Collins
Published on 2010-06-17T14:12:43Z Indexed on 2010/06/17 14:23 UTC
Read the original article Hit count: 255

Filed under:
|
|
|

I have a problem with a subquery involving IPV4 addresses stored in MySQL (MySQL 5.0).

The IP addresses are stored in two tables, both in network number format - e.g. the format output by MySQL's INET_ATON(). The first table ('events') contains lots of rows with IP addresses associated with them, the second table ('network_providers') contains a list of provider information for given netblocks.

events table (~4,000,000 rows):

event_id (int)
event_name (varchar)
ip_address (unsigned 4 byte int)

network_providers table (~60,000 rows):

ip_start (unsigned 4 byte int)
ip_end  (unsigned 4 byte int)
provider_name (varchar)

Simplified for the purposes of the problem I'm having, the goal is to create an export along the lines of:

event_id,event_name,ip_address,provider_name

If do a query along the lines of either of the following, I get the result I expect:

SELECT provider_name FROM network_providers WHERE INET_ATON('192.168.0.1') >= network_providers.ip_start ORDER BY network_providers.ip_start DESC LIMIT 1

SELECT provider_name FROM network_providers WHERE 3232235521 >= network_providers.ip_start ORDER BY network_providers.ip_start DESC LIMIT 1

That is to say, it returns the correct provider_name for whatever IP I look up (of course I'm not really using 192.168.0.1 in my queries).

However, when performing this same query as a subquery, in the following manner, it doesn't yield the result I would expect:

SELECT 
event.id,
event.event_name,
    (SELECT provider_name FROM network_providers 
    WHERE event.ip_address >= network_providers.ip_start 
    ORDER BY network_providers.ip_start DESC LIMIT 1) as provider
FROM events

Instead the a different (incorrect) value for network_provider is returned - over 90% (but curiously not all) values returned in the provider column contain the wrong provider information for that IP.

Using event.ip_address in a subquery just to echo out the value confirms it contains the value I'd expect and that the subquery can parse it. Replacing event.ip_address with an actual network number also works, just using it dynamically in the subquery in this manner that doesn't work for me.

I suspect the problem is there is something fundamental and important about subqueries in MySQL that I don't get. I've worked with IP addresses like this in MySQL quite a bit before, but haven't previously done lookups for them using a subquery.

The question:

I'd really appreciate an example of how I could get the output I want, and if someone here knows, some enlightenment as to why what I'm doing doesn't work so I can avoid making this mistake again.

Notes:

The actual real-world usage I'm trying to do is considerably more complicated (involving joining two or three tables). This is a simplified version, to avoid overly complicating the question.

Additionally, I know I'm not using a between on ip_start & ip_end - that's intentional (the DB's can be out of date, and such cases the owner in the DB is almost always in the next specified range and 'best guess' is fine in this context) however I'm grateful for any suggestions for improvement that relate to the question.

Efficiency is always nice, but in this case absolutely not essential - any help appreciated.

© Stack Overflow or respective owner

Related posts about sql

Related posts about mysql