I think I need to build the data dictionary first based on the list of rows already in the feature layer FinalNetworkLayerName as this restricts the number of row to be processed to between 3000 and 64000, whereas, in total, there are millions of potential rows to be processed. This still looks to me like I need to build the data dictionary row by row, which seems to me will probably result in the same amount of time taken if that time is taken up by mostly the SQL call istelf. However, if it is the update of the feature layer that is the majority of the 2 seconds taken, then there may be a saving, assuming that the building of the data dictionary is quick.
That would mean attempting to build the data dictionary row by row using the list of all objectIDs from FinalNetworkLayerName. So is there efficient code for this process?
Cheers
Mark Wingfield
readFieldsList = ["OBJECTID", "RID", "MEAS", "X_COORD", "Y_COORD", "X_Y_LINK", "STNAME", "STNAMES", "X_Y_ROUTE"] valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(readFC, readFieldsList)} updateFieldsList = ["FROM_OBJECTID","FROM_ROUTE_NAME","FROM_MEASURE","FROM_MEAS","FROM_X_COORDINATE","FROM_Y_COORDINATE","FROM_X_Y_LINK","FROM_STREET_NAME","FROM_CROSS_STREETS","FROM_X_Y_ROUTE_NAME"] with arcpy.da.UpdateCursor(outputFC, updateFieldsList) as updateRows: for updateRow in updateRows: ObjectIDVal = updateRow[0] if ObjectIDVal in valueDict: updateRow[1] = valueDict[ObjectIDVal][0] updateRow[2] = valueDict[ObjectIDVal][1] updateRow[3] = valueDict[ObjectIDVal][1] updateRow[4] = valueDict[ObjectIDVal][2] updateRow[5] = valueDict[ObjectIDVal][3] updateRow[6] = valueDict[ObjectIDVal][4] updateRow[7] = valueDict[ObjectIDVal][5] updateRow[8] = valueDict[ObjectIDVal][6] updateRow[9] = valueDict[ObjectIDVal][7] updateRows.updateRow(updateRow)
Given that there was mention of using a list of objectIDs from the FinalNetworkLayerName feature layer, it would be possible for the function to be part of a SQL Select statement and the objectids passed into this as a Where clause. And then I guess this can be called to create a data dictionary but still unsure about the code.
If this was the solution (and given that I would need to deal with chunks of data as I don't believe SQL Server 2008 can deal with over 60000 entries in a single WHERE.....IN (....)... statement), how would I code:
1. Create a data Dictionary for the first chunk of objectIDs from FinalNetworkLayerName, passing these to the WHERE clause of a SQL statement
2. Update the same Data Dictionary for x chunks of objectIDs, also passing to a WHERE clause, until the end of FinalNetworkLayerName
3. Then update FinalNetworkLayerName by matching to the objectIDs in the Data Dictionary
Cheers
Mark
updateFieldsList = ["FROM_OBJECTID","FROM_ROUTE_NAME","FROM_MEASURE","FROM_MEAS","FROM_X_COORDINATE","FROM_Y_COORDINATE","FROM_X_Y_LINK","FROM_STREET_NAME","FROM_CROSS_STREETS","FROM_X_Y_ROUTE_NAME"] valueDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(outputFC, updateFieldsList)} readFieldsList = ["OBJECTID", "RID", "MEAS", "X_COORD", "Y_COORD", "X_Y_LINK", "STNAME", "STNAMES", "X_Y_ROUTE"] with arcpy.da.SearchCursor(readFC, readFieldsList) as readRows: for readRow in readRows: ObjectIDVal = readRow[0] if ObjectIDVal in valueDict: valueDict[ObjectIDVal][0] = readRow[1] valueDict[ObjectIDVal][1] = readRow[2] valueDict[ObjectIDVal][2] = readRow[2] valueDict[ObjectIDVal][3] = readRow[3] valueDict[ObjectIDVal][4] = readRow[4] valueDict[ObjectIDVal][5] = readRow[5] valueDict[ObjectIDVal][6] = readRow[6] valueDict[ObjectIDVal][7] = readRow[7] valueDict[ObjectIDVal][8] = readRow[8] with arcpy.da.UpdateCursor(outputFC, updateFieldsList) as updateRows: for updateRow in updateRows: ObjectIDVal = updateRow[0] updateRow[1] = valueDict[ObjectIDVal][0] updateRow[2] = valueDict[ObjectIDVal][1] updateRow[3] = valueDict[ObjectIDVal][2] updateRow[4] = valueDict[ObjectIDVal][3] updateRow[5] = valueDict[ObjectIDVal][4] updateRow[6] = valueDict[ObjectIDVal][5] updateRow[7] = valueDict[ObjectIDVal][6] updateRow[8] = valueDict[ObjectIDVal][7] updateRow[9] = valueDict[ObjectIDVal][8] updateRows.updateRow(updateRow)
message = "[INFO] Create table of general GGF data started at " + str(datetime.datetime.now()) print message viewName = "DWOP.DBO.VWO_GenerateGeorouteFilesNonSpatial" fullViewName = arcpy.env.workspace + os.sep + viewName tableLayerName = "GGF_Data" + OfficeID fieldList = [[viewName + ".OBJECTID"],[viewName + ".TOID"],[viewName + ".OFFICE_ID"],[viewName + ".SEG_ID"],[viewName + ".STL_NAME"],[viewName + ".STR_NAME"],[viewName + ".ST_CLASS"],[viewName + ".ORIG_LVL"],[viewName + ".DEST_LVL"],[viewName + ".ONEWAY"],[viewName + ".SPEED1"],[viewName + ".SPEED2"],[viewName + ".SPEED3"],[viewName + ".SPEED4"],[viewName + ".TRN_MODE"],[viewName + ".BTH_MODE"],[viewName + ".RESTR_ORI"],[viewName + ".RESTR_DEST"]] whereClause = "OFFICE_ID = " + OfficeID arcpy.MakeQueryTable_management(fullViewName,tableLayerName,"USE_KEY_FIELDS",viewName + ".OBJECTID",fieldList,whereClause) message = "[INFO] Create Data Dictionary of general GGF data started at " + str(datetime.datetime.now()) print message mySqlFieldsToReturnList = ["OBJECTID",viewName + ".TOID",viewName + ".OFFICE_ID",viewName + ".SEG_ID",viewName + ".STL_NAME",viewName + ".STR_NAME",viewName + ".ST_CLASS",viewName + ".ORIG_LVL",viewName + ".DEST_LVL",viewName + ".ONEWAY",viewName + ".SPEED1",viewName + ".SPEED2",viewName + ".SPEED3",viewName + ".SPEED4",viewName + ".TRN_MODE",viewName + ".BTH_MODE",viewName + ".RESTR_ORI",viewName + ".RESTR_DEST"] rdlkDict = {r[0]:(r[1:]) for r in arcpy.da.SearchCursor(tableLayerName, mySqlFieldsToReturnList)} #Would like to check the rdlkDict values here message = "[INFO] Looping through selected RoadNetwork started at " + str(datetime.datetime.now()) print message updateFieldsList = ["OBJECTID","SEG_ID","STL_NAME","STR_NAME","ST_CLASS", "ORIG_LVL","DEST_LVL","ONEWAY","SPEED1","SPEED2","SPEED3","SPEED4","TRN_MODE","BTH_MODE","RESTR_ORI","RESTR_DEST"] with arcpy.da.UpdateCursor(FinalNetworkLayerName, updateFieldsList) as updateRows: for updateRow in updateRows: ObjectIDVal = updateRow[0] currentRow = currentRow + 1 if currentRow%100 == 0: message = "[INFO] Processed " + str(currentRow) + " of " + str(RoadNetworkCount) + " rows at " + str(datetime.datetime.now()) print message if ObjectIDVal in rdlkDict: updateRow[1] = rdlkDict[ObjectIDVal][3] updateRow[2] = rdlkDict[ObjectIDVal][4] updateRow[3] = rdlkDict[ObjectIDVal][5] updateRow[4] = rdlkDict[ObjectIDVal][6] updateRow[5] = rdlkDict[ObjectIDVal][7] updateRow[6] = rdlkDict[ObjectIDVal][8] updateRow[7] = rdlkDict[ObjectIDVal][9] updateRow[8] = rdlkDict[ObjectIDVal][10] updateRow[9] = rdlkDict[ObjectIDVal][11] updateRow[10] = rdlkDict[ObjectIDVal][12] updateRow[11] = rdlkDict[ObjectIDVal][13] updateRow[12] = rdlkDict[ObjectIDVal][14] updateRow[13] = rdlkDict[ObjectIDVal][15] updateRow[14] = rdlkDict[ObjectIDVal][16] updateRow[15] = rdlkDict[ObjectIDVal][17] updateRows.updateRow(updateRow)
Thanks everybody. The data dictionary method was superfast and has definitely solved a very thorny problem. I did use makequerytable first to get the data into a layer i could interrogate in testing and then used this to populate the data dictionary.
All works very well
Cheers