I'm having a little trouble setting up this script. Here are the bullet points.
- 2 Tables have the same three fields. [SiteID], [EasyID], [FeatureID]. For simplicity, lets pretend these are the only fields (besides OID).
- [FeatureID] is a unique integer for each feature created in Table 1.
- [SiteID] is a non-unique integer and groups features by location.
- [EasyID] is a string (typically a number) unique within the same [SiteID], but not unique in the field.
- Table 1 - The master table. New features have all three ID fields populated.
- Table 2 - New features always have [SiteID], sometimes [EasyID], and never a [FeatureID].
- Table 2 - Features with [SiteID] and [EasyID], and no [FeatureID] may have a matching [SiteID] and [EasyID] in Table 1. If so, update [FeatureID] in Table 2.
- Table 2 - Features missing [EasyID] need to be assigned the next number for that [SiteID] in either Table 1 or 2. If current EasyID's for a site are '1', '3', '4A', '6-7','S', and '55', new features would be '2', '4', '5', '6', '7', '8'....etc.
- Table 2 - New features given a [FeatureID] when inserted into Table 1. The features are then updated in Table 2.
- Table 1 - Finally, any features with a [SiteID] in Table 2, but the [FeatureID] and [EasyID] are not in Table 2, are inserted into Table 2
- At the end of the script both tables should match.
I've looked through using model builder with no luck. With python dictionaries and search cursors i'm getting stuck trying to join against [SiteID] and [EasyID] at the same time. I am also don't know how to return the dictionaries with just integer EasyID's and loop through updating the next smallest integer.
Here is what I've got so far. Much of it stems from what I read from Richard Fairhurst's post Turbo Charging Data Manipulation with Python Cursors and Dictionaries
import arcpy
#Tables
T1 = r"C:\Python\Scratch.gdb\Table1"
T2 = r"C:\Python\Scratch.gdb\Table2"
fields = ["FeatureID", "SiteID", "EasyID"]
# Get FeatureID dictionaries for each Table
T1Dict = {r[0]:(r[0:]) for r in arcpy.da.SearchCursor(T1, fields)}
T2Dict = {r[0]:(r[0:]) for r in arcpy.da.SearchCursor(T2, fields)}
# Get SiteID+EasyID dictionaries for each Table
T1ConcatDict = {str(r[1]) + "," + str(r[2]):(r[0]) for r in arcpy.da.SearchCursor(T1, fields)}
T2ConcatDict = {str(r[1]) + "," + str(r[2]):(r[0]) for r in arcpy.da.SearchCursor(T2, fields)}
#First, If T2.FeatureID is Null but T2.EasyID and T2.SiteID are in T1, Update T2.FeatureID
with arcpy.da.UpdateCursor(T2, fields) as updateRows:
for updateRow in updateRows:
# store the Join value by combining 3 field values of the row being updated in a keyValue variable
keyValue = str(updateRow[1]) + "," + str(updateRow[2])
# verify that the keyValue is in the Dictionary
if keyValue in T1ConcatDict & updateRow[0] is None & updateRow[1] is not None:
# transfer the value stored under the keyValue from the dictionary to the updated field: FeatureID.
updateRow[0] = T1ConcatDict[keyValue][0]
updateRows.updateRow(updateRow)
#Rebuild Dictionary if it is needed again
T2ConcatDict = {str(r[1]) + "," + str(r[2]):(r[0]) for r in arcpy.da.SearchCursor(T2, fields)}
T2Dict = {r[0]:(r[0:]) for r in arcpy.da.SearchCursor(T2, fields)}
'''
#Get Max(EasyID) within SiteID
NumberList = []
for value in T1Dict[2]:
try:
NumberList.append(int(value))
except ValueError:
continue
T1EasyNumberDict = [s[2] for s in T1Dict[2] if s.isdigit()]
T1MaxEasyDict = max(T1EasyNumberDict)
'''
#Second, If T2.FeatureID and T2.EasyID are Null, Update T2.EasyID with next smallest number (as string) in either T1 or T2 for the specific SiteID
with arcpy.da.UpdateCursor(T2, fields) as updateRows:
for updateRow in updateRows:
# store the Join value by combining 3 field values of the row being updated in a keyValue variable
keyValue = str(updateRow[1]) + "," + str(updateRow[2])
# verify that the keyValue is in the Dictionary
if keyValue in T1Dict & updateRow[0] is None & updateRow[1] is None:
# transfer the value stored under the keyValue from the dictionary to the updated field.
# Perhaps retrieve max int occurs here?
updateRow[2] = max(T1Dict[keyValue][2], T2Dict[keyValue[2])
updateRows.updateRow(updateRow)
#Third, Insert into T1 if T2.SiteID is not null and T2.EasyID is not null
#Forth, Update T2.FeatureID with T1.FeatureID from previous insert where T2.SiteID=T1.SiteID and T2.EasyID=T1.EasyID
#Lastly, Insert any T1 features into T2 where T1.EasyID not in (Select EasyID from T2 where T2.SiteID = T1.SiteID) and T1.FeatureID not in (Select FeatureID from T2)
Thank you for any advise.
Edit: Here is a sample of sites with 2 explanatory columns
| T1.FeatureID | T2.FeatureID | T1.SiteID | T2.SiteID | T1.EasyID | T2.EasyID | Status | Result |
| 358589 | 358589 | 136238 | 136238 | 1 | 1 | Existing T1 and T2 Feature | No Change |
| 358590 | 358590 | 136238 | 136238 | 2 | 2 | Existing T1 and T2 Feature | No Change |
| 358594 | 358594 | 136238 | 136238 | 4 | 4 | Existing T1 and T2 Feature | No Change |
| 652538 | 652538 | 136238 | 136238 | 5 | 5 | Existing T1 and T2 Feature | No Change |
| 486028 | 486028 | 136238 | 136238 | 8 | 8 | Existing T1 and T2 Feature | No Change |
| 486029 | 486029 | 136238 | 136238 | 9 | 9 | Existing T1 and T2 Feature | No Change |
| 525300 | 525300 | 136238 | 136238 | 34 | 34 | Existing T1 and T2 Feature | No Change |
| 574802 | 574802 | 136238 | 136238 | 998 | 998 | Existing T1 and T2 Feature | No Change |
| 670911 | | 136238 | | 300 | | New T1 Feature | (Step 6) Inserted Into T2 |
| 493840 | | 136238 | | 9996 | | New T1 Feature | (Step 6) Inserted Into T2 |
| 493839 | | 136238 | | 9997 | | New T1 Feature | (Step 6) Inserted Into T2 |
| 493831 | | 136238 | | 9999 | | New T1 Feature | (Step 6) Inserted Into T2 |
| 696019 | | 136238 | | 105-106 | | New T1 Feature | (Step 6) Inserted Into T2 |
| 696037 | | 136238 | | 9999N | | New T1 Feature | (Step 6) Inserted Into T2 |
| 696014 | | 136238 | | Area1 | | New T1 Feature | (Step 6) Inserted Into T2 |
| 670910 | | 136238 | | N | | New T1 Feature | (Step 6) Inserted Into T2 |
| 580636 | | 136238 | | N30c | | New T1 Feature | (Step 6) Inserted Into T2 |
| 360401 | | 136401 | | AC | | Exiting T1 Feature | (Skip) Not Inserted since no T2.SiteID match |
| 360402 | | 136401 | | SP | | Exiting T1 Feature | (Skip) Not Inserted since no T2.SiteID match |
| 360510 | | 136427 | | Area 1 | | Exiting T1 Feature | (Skip) Not Inserted since no T2.SiteID match |
| 362653 | | 136635 | | 15 | | Exiting T1 Feature | (Skip) Not Inserted since no T2.SiteID match |
| 362943 | 362943 | 136698 | 136698 | 1 | 1 | Existing T1 and T2 Feature | No Change |
| 362944 | 362944 | 136698 | 136698 | 2 | 2 | Existing T1 and T2 Feature | No Change |
| 362945 | 362945 | 136698 | 136698 | 3 | 3 | Existing T1 and T2 Feature | No Change |
| 362946 | 362946 | 136698 | 136698 | 4 | 4 | Existing T1 and T2 Feature | No Change |
| 362947 | 362947 | 136698 | 136698 | 5 | 5 | Existing T1 and T2 Feature | No Change |
| 362950 | 362950 | 136698 | 136698 | 11C | 11C | Existing T1 and T2 Feature | No Change |
| 362948 | 362948 | 136698 | 136698 | 8 | | New T2 Feature, Exists in T1 | (Step 5) Update T2.EasyID |
| 362949 | 362949 | 136698 | 136698 | 9 | | New T2 Feature, Exists in T1 | (Step 5) Update T2.EasyID |
| 362951 | | 136698 | 136698 | 15 | 15 | New T2 Feature, Exists in T1 | (Step 1) Update T2.FeatureID |
| 362954 | | 136698 | 136698 | 16 | 16 | New T2 Feature, Exists in T1 | (Step 1) Update T2.FeatureID |
| 362955 | | 136698 | 136698 | 17 | 17 | New T2 Feature, Exists in T1 | (Step 1) Update T2.FeatureID |
| 362956 | | 136698 | 136698 | 18 | 18 | New T2 Feature, Exists in T1 | (Step 1) Update T2.FeatureID |
| 362957 | | 136698 | 136698 | 19 | 19 | New T2 Feature, Exists in T1 | (Step 1) Update T2.FeatureID |
| | | 136698 | | 20 | New T2 Feature | (Step 3,4) Insterted into T1, Update T2.FeatureID |
| | | 136698 | | 21 | New T2 Feature | (Step 3,4) Insterted into T1, Update T2.FeatureID |
| | | 136698 | | 22 | New T2 Feature | (Step 3,4) Insterted into T1, Update T2.FeatureID |
| | | 136698 | | 25 | New T2 Feature | (Step 3,4) Insterted into T1, Update T2.FeatureID |
| | | 136698 | | | New T2 Feature | (Step 2,3,4) Get next lowest integer for T2.EasyID -> 6 |
| | | 136698 | | | New T2 Feature | (Step 2,3,4) Get next lowest integer for T2.EasyID -> 7 |
| | | 136698 | | | New T2 Feature | (Step 2,3,4) Get next lowest integer for T2.EasyID -> 10 |
| | | 136698 | | | New T2 Feature | (Step 2,3,4) Get next lowest integer for T2.EasyID -> 11 |