Modelbuilder: How to select items from a tabular table base upon a field from another layer

6606
28
Jump to solution
02-03-2015 01:44 PM
TedKowal
Occasional Contributor III

I am an old VB/VB.Net guy and this one has me stumped in terms of building a tool using model builder so any assistance in leading me to a solution will be greatly appreciated.  (I can build a vbs script to this but I am attempting to do this within modelbuilder/python script [if necessary])

Background:

I work for a transportation agency.  Our GIS field collection is based upon new construction projects.  For any project, all of our GIS layers are extracted that fall within a buffered distance of the project along with all the attributes that are associated with the objects.  I felt that this would be a great place to use modelbuilder to make a tool that would do this so my tech's that have no SQL experience can quickly create a MS Access Field Geodatabase.  Old method was to manually export each layer (a process that could take upwards to a week to complete.

I completed 99.9% of the problem within the model and it can create the field database in a matter minutes.  However.....  I have one small problem.

Our traffic signs are stored in the database as two objects: 1.  Sign support (GIS point feature class)  2.  SignPanels which is an independent tabular table.   The linkage between both objects is the  SignSupportID  which is the primary key in the Sign Support layer and foreign key in the tabular table.

Problem:

I would like to create/copy  tabular table of specified fields from the SignPanels table that have a matching Sign Support ID from the Sign support GIS layer (This is a filtered set containing the sign support points within the project area)... This seems to be a simple common problem but I have hit wall.... 

Manually, I would simply create an sql statement selecting those SignPanels that were "in" the filtered sign support gis layer table. Select * from SignPanels SP where SP.SupportID in (Select SupportID from SignSupports where Project = "XXXXX")

Solution or Methodology needed:

.. using Model builder I need a Feature Class and Tabular Table along with  a query that can iterate through the FC for all the ID's ...)  I already have the Filtered GIS layer as an output in the model.  What I now need is to create a table containing my desired attributes of only those panels in the SignPanels table that have a support id that matches the Filtered GIS layer.

Confused?  Any Ideas?

Thanks ahead of time!

Ted

Tags (2)
0 Kudos
28 Replies
BruceHarold
Esri Regular Contributor
0 Kudos
TedKowal
Occasional Contributor III

Tool gives me an error on the input layer or table view parameter ...

file:///C:/Users/tkowal/AppData/Roaming/ESRI/Desktop10.2/ArcToolbox/Dlg/MdDlgContent.htm#ERROR file:///C:/Users/tkowal/AppData/Roaming/ESRI/Desktop10.2/ArcToolbox/Dlg/MdDlgContent.htm#

updateMessage Execution Error: Runtime error Traceback (most recent call last): File "D:\Workspace\MaintUpdate\ProjGIS\KeyfileSelection.tbx#KeyfileSelection.UpdateMessages.py", line 4, in File "D:\Workspace\MaintUpdate\ProjGIS\KeyfileSelection.tbx#KeyfileSelection.UpdateMessages.py", line 31, in updateMessages AttributeError: DescribeData: Method fidset does not exist

The panels table does not have an OID or FID; this is not a GIS table but a regular run of the mill tabular table in a database with its own Primary Key other than an OID that ESRI insists upon.  Too many other processes use this table to change its structure.

0 Kudos
BruceHarold
Esri Regular Contributor

OK, my tool requires OID behavior, but you could try stringing a workflow together in Modelbuilder and precede the tool with a Make Query Table process that dummies up an OID in memory.

regards

0 Kudos
TedKowal
Occasional Contributor III

Same error even using the dummy up make table query.

I even tried a perpared mdb with all the tables having an OID.  Same error!

ToolError.png

0 Kudos
BruceHarold
Esri Regular Contributor

The error is in the tool validation, it looks to be caused by the workspace not supporting selection, is the MDB a Personal Geodatabase or a vanilla Access database?  The tool requires a GDB.

TedKowal
Occasional Contributor III

BTW -- I am on 10.2.2  Don't know why the script did not work.  I ran it in idle using the same DB I sent you,  I even went as far as creating the same temp locations....  Still the same error.  Re-created the Geodatabase ...  with OID's (Esri recognized!)  Still the same error.  Harolds tool -- the MS Access is a personal geodatabase -- however the sign panels are a link to another base pure data.  But the test I am doing for automation, it is not a link but a real table with OID's.....  This project was to try and acomplish 100% automation for creating a field datase for GIS collection.  The techs that would run it have little to no DB/GIS experience -- basically Facebooker's !

I am not a lover of Python because of the reasons I am experiencing -- very temperamental and inconsistant compared to VBA or VB.Net --- there I could trap problems/ repeat them etc....  Seems like I am taking a sledge hammer to perform a very basic sql query .... in any event  I got another methodology to work using Select LayerByAttribute_management and building the select clause.

I still would be interested in figuring out why both Blake and Bruce script/tool was failing (for competeness sake!)

The Script I got to work in my model and my ESRI setup :

import arcpy, os


# Local Variables
OriginTable = arcpy.GetParameterAsText(0) #Sign Support -->   Make Table View
DestinationTable = arcpy.GetParameterAsText(1) #Sign Panels --->  Make Table View
PrimaryKeyField = arcpy.GetParameterAsText(2) #SupportID /Sign Support
ForiegnKeyField = arcpy.GetParameterAsText(3) #SupportID /Sign Panels


def buildWhereClauseFromList(OriginTable, PrimaryKeyField, valueList):
  """Takes a list of values and constructs a SQL WHERE
       clause to select those values within a given PrimaryKeyField
       and OriginTable."""


  fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(OriginTable).path, PrimaryKeyField)


  # Determine field type
  fieldType = arcpy.ListFields(OriginTable, PrimaryKeyField)[0].type
  # Add DBMS-specific field delimiters


  # Add single-quotes for string field values
  if str(fieldType) == 'String':
    valueList = ["'%s'" % value for value in valueList]


  # Format WHERE clause in the form of an IN statement
  whereClause = "%s IN(%s)" % (fieldDelimited, ', '.join(map(str, valueList)))
  arcpy.AddMessage(whereClause)
  return whereClause


def selectRelatedRecords(OriginTable, DestinationTable, PrimaryKeyField, ForiegnKeyField):
    """Defines the record selection from the record selection of the OriginTable
      and apply it to the DestinationTable using a SQL WHERE clause built
      in the previous definition"""


    # Set the SearchCursor to look through the selection of the OriginTable
    sourceIDs = set([row[0] for row in arcpy.da.SearchCursor(OriginTable, PrimaryKeyField)])


    # Establishes the where clause used to select records from DestinationTable
    whereClause = buildWhereClauseFromList(DestinationTable, ForiegnKeyField, sourceIDs)


    # Process: Select Layer By Attribute
    arcpy.SelectLayerByAttribute_management(DestinationTable, "NEW_SELECTION", whereClause)


# Process: Select related records between OriginTable and DestinationTable
selectRelatedRecords(OriginTable, DestinationTable, PrimaryKeyField, ForiegnKeyField) #output same as Destination Table
0 Kudos
TedKowal
Occasional Contributor III

Another note.... The script even honors the db link to another database where the real resides... go figure  I would have sworn the script choke on that!

0 Kudos
BlakeTerhune
MVP Regular Contributor

Sorry for all the trouble but I'm glad you got something to work!

0 Kudos
TedKowal
Occasional Contributor III

Thanks for your help.  I still wonder why the script worked on your system/set and not mine -- it appears that we are running the same versions. I am still keeping your script for future investigation/testing --- It is well written! Ted

0 Kudos