Вибір функцій за атрибутом, якщо у списку Python?


14

Я намагаюся завершити виділення за атрибутом у Python, але виходячи з запиту про те, чи присутній атрибут у списку.

Такий запит у його найпростішому випадку повинен бути приблизно таким:

qry = " \"OBJECTID\" in oid_list"
arcpy.SelectLayersByAttribute_management(inft, "NEW_SELECTION", qry)

але такий підхід повертає недійсну помилку вираження.

Раніше мені довелося використовувати складніший ситаксис для такого типу запитів, як-от:

sqlQuery2 = "nid in (" + ','.join(["'"+x+"'" for x in delta_list]) +")"

але, здається, адаптація цього фрагмента не працює і для мене, тобто:

 "OBJECTID_1 in (" + ','.join(["'"+str(x)+"'" for x in oid_list]) +")"

Що я тут пропускаю?

Відповіді:


16

Ваш початковий запит міг бути змінений для списку цілих чисел:

'"OBJECTID_1" IN ' + str(tuple(oid_list))

так що якщо oid_list = [7, 9, 4, 8], то результат такий:

"OBJECTID_1" IN (7, 9, 4, 8)

Майте на увазі, що цей "трюк" працює, якщо oid_listзавжди є два або більше елементів, оскільки інші дійсні кортежі, такі як ()або (7,), призведе до помилки синтаксису SQL.

Більш загальним виразом, який також оброблятиме нуль або один oid_listпредмет, буде:

'"OBJECTID_1" IN ({0})'.format(', '.join(map(str, oid_list)) or 'NULL')

Я не усвідомлював інтерфейс вибору ArcGIS, підтримуваний "IN". Це, мабуть, ефективніше, ніж моє рішення.
Високий

1
Будьте обережні, є верхня межа, яка підтримується запитом IN Я думаю, що це 2000 записів
Tristan Forward

9

Ось трохи змінена версія функції в цій відповіді , щоб прийняти список Python замість розділеної крапкою з комою:

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

    # Add DBMS-specific field delimiters
    fieldDelimited = arcpy.AddFieldDelimiters(arcpy.Describe(table).path, field)

    # Determine field type
    fieldType = arcpy.ListFields(table, field)[0].type

    # 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)))
    return whereClause

6

Я думаю, що найпростіший підхід до цього полягає в перегляді значень у вашому списку синхронно та доданні їх до вибору (Так ви можете змінити свій запит із кожним значенням у списку). Щось на зразок цього:

oidList = [1,2,3,4]
arcpy.management.MakeFeatureLayer(thisFC,thisLyr)
for values in oidList:
    query = "\"OBJECTID\"="+str(values)
    arcpy.management.SelectLayerByAttribute(thisLyr,"ADD_TO_SELECTION",query)

Ви можете використовувати ADD_TO_SELECTION, навіть якщо немає вибраних функцій, це створить новий вибір при першій ітерації.

Редагувати:

Якщо ви думаєте, що вартість виконання окремих SelectLayerByAttribute буде занадто високою, ви можете скористатися таким підходом, коли ви створите досить велику пропозицію вибору залежно від довжини списку:

oidList = [1,2,3,4]
arcpy.management.MakeFeatureLayer(thisFC,thisLyr)
query=""
q=""
oidList.sort()
for x in oidList:
    query="\"OBJECTID\"="+str(x)+" OR "+q
    q=query
q=q[1:-4]
arcpy.management.SelectLayerByAttribute(thisLyr,"NEW_SELECTION",q)

Цікава ідея провести повторення значень та виконати виділення за атрибутом для кожної ітерації. Я перевірю це, але я впевнений, що це має спрацювати. Спасибі.
jsnider

це, здається, працює, але, безумовно, буде потрібно деякий час для обробки кожного окремого вибору для більш довгих списків.
jsnider

2
Оновили відповідь з іншим підходом.
Високий

Гарна ідея з оновленою відповіддю. Я вирішив використовувати цей підхід, оскільки він набагато швидше обробляє більші списки. Трохи модифікований: q = "" для x в oid_set: query = '"OBJECTID_1" =' + str (x) + 'OR' q = запит q = q [1: -4], а потім виберітьbyattribute. Здається, працює!
jsnider

Я оновлю свою відповідь вашим обраним підходом, щоб вона була проаналізована і легша для читання. Радий, що це спрацювало.
Високий
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.