I am an enthusiastic dabbler in Python and I have (enthusiastically) attempted to write a script to create a one-to-many join to populate rows in the source table (Table1) from data in the join table (Table2).
(I have attached a diagram which explains this process)
The tables will have two ID values - one will have duplicates (ID1) and the other will be unique (ID2).
Table1 has unique IDs which will be duplicated after processing (ID1).
Table2 has two ID fields - there are duplicate ID1's and unique values for ID2.
I need to populate rows from table2 to table1.
The first match will populate the existing row in table1.
All subsequent matches to ID1 will be populated as new rows.
My script currently processes the one-to-many join successfully...but only when there is a maximum of 1 duplicate.
When there is more than 1 new row to insert, my script inserts all rows as duplicates of the 'final matched' row.
If there is anybody who can spot the error in my code or point me in the right direction, I would be really grateful as I have been stuck at this roadblock for a while now....
Thank you for taking the time to read about my troubles
Megan
<SPAN class="keyword token">import</SPAN> arcpy
arcpy<SPAN class="punctuation token">.</SPAN>env<SPAN class="punctuation token">.</SPAN>overwriteOutput <SPAN class="operator token">=</SPAN> <SPAN class="token boolean">True</SPAN>
aprx <SPAN class="operator token">=</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>mp<SPAN class="punctuation token">.</SPAN>ArcGISProject<SPAN class="punctuation token">(</SPAN>r<SPAN class="string token">'C:\sample_aprx.aprx'</SPAN><SPAN class="punctuation token">)</SPAN>
m <SPAN class="operator token">=</SPAN> aprx<SPAN class="punctuation token">.</SPAN>listMaps<SPAN class="punctuation token">(</SPAN><SPAN class="string token">"Map"</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="comment token"># Source table to populate - contains unique ID1's and no ID2 data</SPAN>
table1 <SPAN class="operator token">=</SPAN> r<SPAN class="string token">'C:\sample_aprx.gdb\table1'</SPAN>
table1_fields_update
table1_fields <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="string token">"ID1"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"ID2"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD1"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD2"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD3"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD4"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD5"</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="comment token"># Source table - dictionary with unique keys for ID1</SPAN>
table1_dict <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">{</SPAN>r<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">(</SPAN>r<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">for</SPAN> r <SPAN class="keyword token">in</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>SearchCursor<SPAN class="punctuation token">(</SPAN>table1<SPAN class="punctuation token">,</SPAN>table1_fields<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">}</SPAN>
<SPAN class="comment token"># Join table - duplicate ID1's and unique ID2's</SPAN>
table2 <SPAN class="operator token">=</SPAN> r<SPAN class="string token">'C:\sample_aprx.gdb\table2'</SPAN>
table2_fields <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="string token">"ID1"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"ID2"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD3"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD4"</SPAN><SPAN class="punctuation token">,</SPAN><SPAN class="string token">"FIELD5"</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="comment token"># Join table - dictionary with unique tuples (ID1, ID2) as keys</SPAN>
table2_dict <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">{</SPAN><SPAN class="punctuation token">(</SPAN>r<SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">:</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="punctuation token">(</SPAN>r<SPAN class="punctuation token">[</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">:</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">for</SPAN> r <SPAN class="keyword token">in</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>SearchCursor<SPAN class="punctuation token">(</SPAN>table2<SPAN class="punctuation token">,</SPAN>table2_fields<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">}</SPAN>
<SPAN class="comment token"># List to store rows that need to be inserted</SPAN>
InsertRows_list <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="keyword token">with</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>UpdateCursor<SPAN class="punctuation token">(</SPAN>table1<SPAN class="punctuation token">,</SPAN> table1_fields<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">as</SPAN> UpdateCursor<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">for</SPAN> row <SPAN class="keyword token">in</SPAN> UpdateCursor<SPAN class="punctuation token">:</SPAN>
rowStatus <SPAN class="operator token">=</SPAN> <SPAN class="string token">""</SPAN>
<SPAN class="comment token"># create list of table2 records that match to ID1 in table1</SPAN>
table2match_list <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="punctuation token">(</SPAN>k<SPAN class="punctuation token">,</SPAN> table2_dict<SPAN class="punctuation token">[</SPAN>k<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">for</SPAN> k <SPAN class="keyword token">in</SPAN> table2_dict <SPAN class="keyword token">if</SPAN> k<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">==</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="keyword token">for</SPAN> table2match <SPAN class="keyword token">in</SPAN> table2match_list<SPAN class="punctuation token">:</SPAN>
<SPAN class="comment token"># if "ID2" is already populated from table2, then mark this row as a new row to insert</SPAN>
<SPAN class="keyword token">if</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="keyword token">is</SPAN> <SPAN class="operator token">not</SPAN> None<SPAN class="punctuation token">:</SPAN>
rowStatus <SPAN class="operator token">=</SPAN> <SPAN class="string token">"Insert"</SPAN>
<SPAN class="comment token"># Assign data from table2 to table1</SPAN>
<SPAN class="comment token"># updating fields: ID2, FIELD3, FIELD4, FIELD5</SPAN>
row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">4</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">5</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">6</SPAN><SPAN class="punctuation token">]</SPAN> <SPAN class="operator token">=</SPAN> table2match<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> table2match<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> table2match<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN> table2match<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">]</SPAN>
<SPAN class="comment token">############# This part of the script doesn't work.</SPAN>
<SPAN class="comment token">############# The result 'InsertRows_list' will append 'dupe' table rows to insert (it always dupes the 'last' matched row from table2match_list)</SPAN>
<SPAN class="comment token"># Data that needs to be inserted as new rows is appended to a list, to be processed later </SPAN>
<SPAN class="keyword token">if</SPAN> rowStatus <SPAN class="operator token">==</SPAN> <SPAN class="string token">"Insert"</SPAN>
InsertRows_list<SPAN class="punctuation token">.</SPAN>append<SPAN class="punctuation token">(</SPAN>row<SPAN class="punctuation token">)</SPAN>
<SPAN class="comment token"># If row has not already been populated, then update the existing row in table1</SPAN>
<SPAN class="keyword token">else</SPAN><SPAN class="punctuation token">:</SPAN>
UpdateCursor<SPAN class="punctuation token">.</SPAN>updateRow<SPAN class="punctuation token">(</SPAN>row<SPAN class="punctuation token">)</SPAN>
<SPAN class="comment token"># Insert all new rows</SPAN>
<SPAN class="keyword token">with</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>InsertCursor<SPAN class="punctuation token">(</SPAN>table1<SPAN class="punctuation token">,</SPAN> table1_fields<SPAN class="punctuation token">)</SPAN> <SPAN class="keyword token">as</SPAN> InsertCursor<SPAN class="punctuation token">:</SPAN>
<SPAN class="keyword token">for</SPAN> table2_row_data <SPAN class="keyword token">in</SPAN> InsertRows_list<SPAN class="punctuation token">:</SPAN>
<SPAN class="comment token"># Retrive the existing row in table1 that matches ID1</SPAN>
table1_row_data <SPAN class="operator token">=</SPAN> table1_dict<SPAN class="punctuation token">.</SPAN>get<SPAN class="punctuation token">(</SPAN>row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN>
<SPAN class="comment token"># New row is joined with data from table1 and table2</SPAN>
new_join_row <SPAN class="operator token">=</SPAN> <SPAN class="punctuation token">(</SPAN>table1_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>table2_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>table1_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>table1_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">3</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>table2_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>table2_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">,</SPAN>table2_row_data<SPAN class="punctuation token">[</SPAN><SPAN class="number token">2</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN>
InsertCursor<SPAN class="punctuation token">.</SPAN>insertRow<SPAN class="punctuation token">(</SPAN>new_join_row<SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>