<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Troubleshooting proc sql when merging on a range of ip addresses in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691448#M210457</link>
    <description>&lt;P&gt;Are you sort of trying to do an IP country look up?&amp;nbsp; In other words, if I have an IP address and it's within one of those ranges, I return the corresponding country as the country for that IP address?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If so, you have a bit of a data problem.&amp;nbsp; None of those IP addresses are within any of those ranges.&amp;nbsp; You can write SQL until you're blue in the face and not get any matches.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, if we re-make our test data like so, now we're in business:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data temp_table;
	input	_start_ip_int	1-11 
			_end_ip_int		12-21  
			Edge_Country	$23-24;
	datalines;
1227141270 1227141290 GB
415250900  415250930  US
403411530  403411540  DE
;	
run;


data temp_table2;
	input IP_Numeric 1-11;
	datalines;
1227141285
415250910
415250920
415250930
403411535
;	
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now, this is pretty old school, but I'm going to do the look up using a multi-level array.&amp;nbsp; I'll say more about why I'm doing this, below.&amp;nbsp; For now, here's the code:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;PROC	SQL;
	SELECT		STRIP(PUT(COUNT(1),10.))
		INTO	:	Rows
		FROM	Temp_Table;
QUIT;

%PUT	NOTE:  &amp;amp;=Rows;

DATA	Temp_Table3;
	DROP	_:;
	FORMAT	IP_Numeric	11.;
	IF	_N_									=	1			THEN
		DO;
			DO	UNTIL	(End_Of_Data);
				_Iteration					+	1;
				SET		Temp_Table	END	=	End_Of_Data;
				ARRAY	IP_Range	[&amp;amp;Rows, 2]	_TEMPORARY_;
				ARRAY	Country		[&amp;amp;Rows]	$2	_TEMPORARY_;
				IP_Range	[_Iteration, 1]	=	_start_ip_int;
				IP_Range	[_Iteration, 2]	=	_end_ip_int;
				Country		[_Iteration]	=	Edge_Country;
			END;
		END;

	CALL	MISSING(_Start_IP_Int, _End_IP_Int, Edge_Country);

	SET	Temp_Table2;
	DO	_i									=	1	TO	&amp;amp;Rows;
		_Start_IP_Int						=	IP_Range[_i, 1];
		_End_IP_Int							=	IP_Range[_i, 2];
		IF	_Start_IP_Int	&amp;lt;=	IP_Numeric	&amp;lt;=	_End_IP_Int	THEN
			Edge_Country					=	Country[_i];
	END;
RUN;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;And of course we want results.&amp;nbsp; Notice now that each IP address has been assigned a country based on the ranges.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jimbarbour_0-1602647985474.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/50643i53C478B53F5D0B89/image-size/medium?v=v2&amp;amp;px=400" role="button" title="jimbarbour_0-1602647985474.png" alt="jimbarbour_0-1602647985474.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;OK, so why this (very) old school multi-level array business?&amp;nbsp; Well, while it is more work to code a Data step (generally) than SQL, you have &lt;STRONG&gt;&lt;EM&gt;much&lt;/EM&gt;&lt;/STRONG&gt; more powerful tools debugging tools (Typically PUTLOG and LDEBUG) available.&amp;nbsp; If something isn't working, I fall back to a Data step where I can do a PUTLOG after every line (if necessary) or execute interactively, line by line, with the LDEBUG option.&amp;nbsp; Display Manager supports LDEBUG and Enterprise Guide from version 7.1.3 onward also supports LDEBUG.&amp;nbsp; I believe SAS Studio does too.&amp;nbsp; Once I turned on LDEBUG, the problem was obvious:&amp;nbsp; Those IP addresses and those ranges are a no match.&amp;nbsp; They don't correspond to one another.&amp;nbsp; A quick data makeover rectifies the problem, and, voila, we have assigned each IP a country.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this was what you were after, but even if not, you have been exposed to a technique I don't see much any more, multi-level TEMPORARY arrays used as a look up table.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jim&lt;/P&gt;</description>
    <pubDate>Wed, 14 Oct 2020 04:10:43 GMT</pubDate>
    <dc:creator>jimbarbour</dc:creator>
    <dc:date>2020-10-14T04:10:43Z</dc:date>
    <item>
      <title>Troubleshooting proc sql when merging on a range of ip addresses</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691434#M210451</link>
      <description>&lt;P&gt;I'm not sure why my merge is failing:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;
data temp_table;
	input start_ip_int 1-11 end_ip_int 12-21  edge_country $23-24;
	datalines;
1227141270 1227141290 GB
415250900  415250930  US
403411530  403411540  DE
;	
run;


data temp_table2;
	input ip_numeric 1-11;
	datalines;
1844552390
2452812925 
3001796479
1844552383
;	
run;


proc sql;
	  create table ip_match as
	  select  a.start_ip_int,
	  		  a.end_ip_int,
	  		  a.edge_country,
	  		  b.ip_numeric	  		
	  from  temp_table a
	  		left join
	  		temp_table2 b
	  		on a.start_ip_int &amp;lt;= b.ip_numeric &amp;lt;= a.end_ip_int;   
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Edit: Thank you everyone for the responses!&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 14 Oct 2020 13:25:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691434#M210451</guid>
      <dc:creator>SAShole</dc:creator>
      <dc:date>2020-10-14T13:25:23Z</dc:date>
    </item>
    <item>
      <title>Re: Troubleshooting proc sql when merging on a range of ip addresses</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691438#M210454</link>
      <description>&lt;P&gt;If I understand your question, you have your left join inverted.&amp;nbsp; But I don't think I do because none of your "IP" ranges overlap any of the values in table2.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Are you trying to do something like this?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data temp_table;
	input start_ip_int 1-11 end_ip_int 13-22  edge_country $25-26;
	datalines;
1844552000  1844552999  GB
2452812000  2452813000  US
3001796000  3001796999  DE
;	
run;


data temp_table2;
	input ip_numeric 1-11;
	datalines;
1844552390
2452812925 
3001796479
1844552383
;	
run;


proc sql;
	  create table ip_match as
	  select  a.start_ip_int,
	  		  a.end_ip_int,
	  		  a.edge_country,
	  		  b.ip_numeric	  		
	  from temp_table2 b 
	  	  left join
	  		temp_table a
	  		on a.start_ip_int &amp;lt;= b.ip_numeric &amp;lt;= a.end_ip_int;   
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 14 Oct 2020 01:13:20 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691438#M210454</guid>
      <dc:creator>CurtisMackWSIPP</dc:creator>
      <dc:date>2020-10-14T01:13:20Z</dc:date>
    </item>
    <item>
      <title>Re: Troubleshooting proc sql when merging on a range of ip addresses</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691448#M210457</link>
      <description>&lt;P&gt;Are you sort of trying to do an IP country look up?&amp;nbsp; In other words, if I have an IP address and it's within one of those ranges, I return the corresponding country as the country for that IP address?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If so, you have a bit of a data problem.&amp;nbsp; None of those IP addresses are within any of those ranges.&amp;nbsp; You can write SQL until you're blue in the face and not get any matches.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, if we re-make our test data like so, now we're in business:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data temp_table;
	input	_start_ip_int	1-11 
			_end_ip_int		12-21  
			Edge_Country	$23-24;
	datalines;
1227141270 1227141290 GB
415250900  415250930  US
403411530  403411540  DE
;	
run;


data temp_table2;
	input IP_Numeric 1-11;
	datalines;
1227141285
415250910
415250920
415250930
403411535
;	
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now, this is pretty old school, but I'm going to do the look up using a multi-level array.&amp;nbsp; I'll say more about why I'm doing this, below.&amp;nbsp; For now, here's the code:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;PROC	SQL;
	SELECT		STRIP(PUT(COUNT(1),10.))
		INTO	:	Rows
		FROM	Temp_Table;
QUIT;

%PUT	NOTE:  &amp;amp;=Rows;

DATA	Temp_Table3;
	DROP	_:;
	FORMAT	IP_Numeric	11.;
	IF	_N_									=	1			THEN
		DO;
			DO	UNTIL	(End_Of_Data);
				_Iteration					+	1;
				SET		Temp_Table	END	=	End_Of_Data;
				ARRAY	IP_Range	[&amp;amp;Rows, 2]	_TEMPORARY_;
				ARRAY	Country		[&amp;amp;Rows]	$2	_TEMPORARY_;
				IP_Range	[_Iteration, 1]	=	_start_ip_int;
				IP_Range	[_Iteration, 2]	=	_end_ip_int;
				Country		[_Iteration]	=	Edge_Country;
			END;
		END;

	CALL	MISSING(_Start_IP_Int, _End_IP_Int, Edge_Country);

	SET	Temp_Table2;
	DO	_i									=	1	TO	&amp;amp;Rows;
		_Start_IP_Int						=	IP_Range[_i, 1];
		_End_IP_Int							=	IP_Range[_i, 2];
		IF	_Start_IP_Int	&amp;lt;=	IP_Numeric	&amp;lt;=	_End_IP_Int	THEN
			Edge_Country					=	Country[_i];
	END;
RUN;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;And of course we want results.&amp;nbsp; Notice now that each IP address has been assigned a country based on the ranges.&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jimbarbour_0-1602647985474.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/50643i53C478B53F5D0B89/image-size/medium?v=v2&amp;amp;px=400" role="button" title="jimbarbour_0-1602647985474.png" alt="jimbarbour_0-1602647985474.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;OK, so why this (very) old school multi-level array business?&amp;nbsp; Well, while it is more work to code a Data step (generally) than SQL, you have &lt;STRONG&gt;&lt;EM&gt;much&lt;/EM&gt;&lt;/STRONG&gt; more powerful tools debugging tools (Typically PUTLOG and LDEBUG) available.&amp;nbsp; If something isn't working, I fall back to a Data step where I can do a PUTLOG after every line (if necessary) or execute interactively, line by line, with the LDEBUG option.&amp;nbsp; Display Manager supports LDEBUG and Enterprise Guide from version 7.1.3 onward also supports LDEBUG.&amp;nbsp; I believe SAS Studio does too.&amp;nbsp; Once I turned on LDEBUG, the problem was obvious:&amp;nbsp; Those IP addresses and those ranges are a no match.&amp;nbsp; They don't correspond to one another.&amp;nbsp; A quick data makeover rectifies the problem, and, voila, we have assigned each IP a country.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this was what you were after, but even if not, you have been exposed to a technique I don't see much any more, multi-level TEMPORARY arrays used as a look up table.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Jim&lt;/P&gt;</description>
      <pubDate>Wed, 14 Oct 2020 04:10:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691448#M210457</guid>
      <dc:creator>jimbarbour</dc:creator>
      <dc:date>2020-10-14T04:10:43Z</dc:date>
    </item>
    <item>
      <title>Re: Troubleshooting proc sql when merging on a range of ip addresses</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691452#M210458</link>
      <description>&lt;P&gt;Storing ip-addresses as numerics can cause trouble:&lt;/P&gt;
&lt;P&gt;100.&lt;FONT color="#339966"&gt;1&lt;/FONT&gt;.&lt;FONT color="#3366FF"&gt;201&lt;/FONT&gt;.&lt;FONT color="#993366"&gt;55&lt;/FONT&gt; = &lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;100&lt;FONT color="#339966"&gt;1&lt;/FONT&gt;&lt;FONT color="#3366FF"&gt;201&lt;/FONT&gt;&lt;FONT color="#993366"&gt;55&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;100.&lt;FONT color="#339966"&gt;120&lt;/FONT&gt;.&lt;FONT color="#3366FF"&gt;15&lt;/FONT&gt;.&lt;FONT color="#993366"&gt;5&lt;/FONT&gt; = &lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;100&lt;FONT color="#339966"&gt;120&lt;/FONT&gt;&lt;FONT color="#3366FF"&gt;15&lt;/FONT&gt;&lt;FONT color="#993366"&gt;5&lt;/FONT&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 14 Oct 2020 04:54:40 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Troubleshooting-proc-sql-when-merging-on-a-range-of-ip-addresses/m-p/691452#M210458</guid>
      <dc:creator>andreas_lds</dc:creator>
      <dc:date>2020-10-14T04:54:40Z</dc:date>
    </item>
  </channel>
</rss>

