If you enter map coordinates in the traditional fashion, the Y coordinate is entered directly as a number, but the X coordinate needs to be represented twice: once as a letter or pair of letters, and once as a numeric coordinate.
The Family table would have at least these fields to hold this data: Family (text), Helps (yes/no), Needs (yes/no), XLtr (text), XNr (number), and YNr (number). Define the X and Y coordinates as numeric; because, you'll soon have the database do math with them.
Here are some sample records to help you experiment:
FAMILY,HELPS,NEEDS,XLtr,XNr,YNr Fenwick,0,1,M,13,19 Roberts,0,1,M,13,21 Quales,1,1,N,14,18 Vance,0,1,O,15,19 Crowley,0,1,P,16,15 Dobbs,1,1,P,16,21 Jameson,0,1,R,18,10 Mack,1,0,R,18,18 Lubbock,0,1,R,18,19 Eggbert,0,1,R,18,21 Hicks,1,1,S,19,18 Thompson,1,1,S,19,18 Stanford,0,1,S,19,20 Jones,1,1,T,20,20
Put all the code into mapdist.cfm. This query will update XNr with the appropriate numbers.
<!--- Convert X letters to numbers ---> <cfquery name="setLabel" datasource="context"> update Family, Label set Family.XNr = Label.XNr where Family.XLtr = Label.Label </cfquery>
Use the same table two different ways by giving it two different aliases. For this example, let the "a" alias represent Families and the "b" alias represent Helpers. So, the Family result from this query will be a.Family. Its X and Y coordinates are a.XNr and a.YNr. (Its X-lettered coordinate is a.XLtr.) The Helper result from this query will be b.Family because of the way that these records are picked (as you'll see later). Its X and Y coordinates are b.XNr and b.YNr (and its X-lettered coordinate is b.XLtr). Finally, the big equation to determine distance must be used. It's just the formula you're used to using for the hypotenuse except that the final result is multiplied by the distance between adjacent map coordinates: the size of a map cell. For this example, let the size of a map cell be .857 miles. Because the alias "distance" won't be recognized within the query, you have to repeat the entire formula each place it is needed.
The rows in the Family table used as the "a" alias are those whose Needs field is true. The rows in the Family table used as the "b" alias are those whose Helps field is true. You don't want rows whose distance could not be calculated. (Perhaps the coordinates weren't available.) You don't want the situation where a Family visits itself to be part of the query; so, exclude rows where Family (a.Family) equals Helper (b.Family). Finally, sequence the query by distance so you can consider the pairs having the shortest distance first.
<!--- Determine the distance between each pair and order by shortest distance first ---> <cfquery name="tryAll" datasource="context"> select a.family as Helper, a.XLtr as HelperLtr, a.XNr as HelperX, a.YNr as HelperY, b.Family as Family, b.XLtr as FamilyLtr, b.XNr as FamilyX, b.YNr as FamilyY, ((a.XNr-b.XNr)^2+(a.YNr-b.YNr)^2)^.5*.857 as Distance from Family a, Family b where a.helps = TRUE and b.needs = TRUE and a.family <> b.family and ((a.XNr-b.XNr)^2+(a.YNr-b.YNr)^2)^.5*.857 <> NULL order by ((a.XNr-b.XNr)^2+(a.YNr-b.YNr)^2)^.5*.857 </cfquery>
<table> <tr><td>HELPER</td><td>GRID</td> <td>FAMILY</td><td>GRID</td> <td>MILES</td></tr> <cfoutput query="tryAll"> <tr><td>#Helper#</td><td>#HelperLtr##HelperY#</td> <td>#Family#</td><td>#FamilyLtr##FamilyY#</td> <td>#evaluate(round(Distance*1000)/1000)#</td></tr> </cfoutput> </table>
Browse mapdist.cfm to view the result. =Marty=