Vous trouverez ci-dessous le code que j'utilise pour répliquer le bouton "tables associées" dans ArcMap. Dans ArcMap, ce bouton sélectionne des entités dans une classe d'entités ou une table en fonction de la sélection d'entités dans une autre classe d'entités ou table associée.
Dans ArcMap, je peux utiliser ce bouton pour "pousser" ma sélection vers la table associée en quelques secondes. Je n'ai pas pu trouver quoi que ce soit intégré à arcpy qui reproduise le bouton, j'ai donc utilisé des boucles imbriquées pour faire la même tâche.
Le code ci-dessous fait une boucle à travers un tableau de "traitements". Pour chaque traitement, il parcourt une liste "d'arbres". Lorsqu'une correspondance est trouvée entre les champs ID de traitement et les arbres, une sélection se produit dans la couche d'arbre. Une fois qu'une correspondance est trouvée pour un traitement, le code ne continue pas de rechercher dans la couche d'arborescence des correspondances supplémentaires. Il revient à la table de traitement, sélectionne le traitement suivant et effectue une nouvelle recherche dans la classe d'entités arborescentes.
Le code lui-même fonctionne bien, mais il est terriblement lent. La "table de traitement" contient dans ce cas 16 000 enregistrements. La classe d'entités "arborescence" contient 60 000 enregistrements.
Existe-t-il un autre moyen plus efficace de recréer ce que fait ESRI quand il pousse la sélection d'une table à une autre? Dois-je créer un index pour les tables? REMARQUE: ces données sont stockées dans un SDE.
# Create search cursor to loop through the treatments
treatments = arcpy.SearchCursor(treatment_tv)
treatment_field = "Facility_ID"
for treatment in treatments:
#Get ID of treatment
treatment_ID = treatment.getValue(treatment_field)
# Create search cursor for looping through the trees
trees = arcpy.SearchCursor(tree_fl)
tree_field = "FACILITYID"
for tree in trees:
# Get FID of tree
tree_FID = tree.getValue(tree_field)
if tree_FID == treatment_FID:
query = "FACILITYID = " + str(tree_FID)
arcpy.SelectLayerByAttribute_management(tree_fl, "REMOVE_FROM_SELECTION", query)
break
Réponses:
Tout d'abord, oui, vous voudrez certainement vous assurer que vos champs de clé primaire et étrangère sont indexés sur les deux tables. Cela permet au SGBD de planifier et d'exécuter des requêtes sur ces champs beaucoup plus efficacement.
Deuxièmement, vous appelez
SelectLayerByAttribute_management
dans une boucle imbriquée serrée (une fois par arbre par traitement). Ceci est très inefficace, pour plusieurs raisons:Au lieu de cela, refactorisez votre code afin d'appeler
SelectLayerByAttribute_management
une seule fois avec une clause de construction conçue pour sélectionner tous les enregistrements associés.En empruntant une fonction à une autre réponse pour la logique de construction où, je suppose que cela ressemblerait à quelque chose comme ceci:
Vous pourriez l'appeler ainsi:
selectRelatedRecords(treatment_tv, tree_fl, "Facility_ID", "FACILITYID")
Remarques:
Cela utilise un
arcpy.da.SearchCursor
, uniquement disponible à la version 10.1. Comme l'a mentionné @PolyGeo, ces curseurs sont beaucoup plus rapides que leurs prédécesseurs (arcpy.SearchCursor
). Il pourrait être facilement modifié pour utiliser l'ancien SearchCursor cependant:Si votre géodatabase SDE se trouve sur Oracle, soyez averti que l'
IN
instruction utilisée dans la fonction de la réponse liée est limitée à 1 000 éléments. Une solution possible est décrite dans cette réponse , mais vous devrez modifier la fonction pour la diviser en plusieursIN
instructions de longueur 1000 au lieu d'une.la source
La solution ci-dessus fonctionne très bien pour moi et a été très rapide. En utilisant le code ci-dessus et le code référencé de l'autre post, voici comment je l'ai construit:
la source