Как правильно отсортировать, сгруппировать запрос, который возвращает кортеж объекта orm и пользовательский столбец? - PullRequest
2 голосов
/ 05 августа 2011

Я ищу способ получить запрос, который возвращает кортеж, сначала отсортированный по столбцу, а затем сгруппированный по другому (в этом порядке).Просто .sort_by().group_by() не работает.Теперь я попробовал следующее, что привело к неправильному возвращаемому значению (я только что получил объект orm, а не исходный кортеж), но прочитал для себя подробно:

Базовый сценарий:

Существует запрос, который запрашивает объекты тестовой формы, связанные с таблицей test3 через внешние ключи.Этот запрос также возвращает столбец с именем linked, который содержит либо true, либо false.Изначально он не сгруппирован.

my_query = session.query(test_orm_object)
... lots of stuff like joining various things ...
add_column(..condition that either puts 'true' or 'false' into the column..)

Таким образом, исходное возвращаемое значение является кортежем (объект orm, а также столбец true / false).

Теперь этот запрос должен быть сгруппирован дляпроверять объекты orm (например, столбец test.id), но перед этим сортировать по связанному столбцу, поэтому при группировке предпочтительнее вводить записи с true.

Предполагая, что текущий несортированный, разгруппированный запрос сохраняется в my_queryМой подход к достижению этого был такой:

# Get a sorted subquery
tmpquery = my_query.order_by(desc('linked')).subquery()   
# Read the column out of the sub query    
my_query = session.query(tmpquery).add_columns(getattr(tmpquery.c,'linked').label('linked'))  
my_query = my_query.group_by(getattr(tmpquery.c, 'id')) # Group objects

Результирующий запрос SQL при выполнении этого (мне кажется, что это нормально - подзапрос 'anon_1' внутри себя правильно отсортирован, затем извлечен иизвлекается его идентификатор, а также извлекается столбец 'linked' (среди нескольких других столбцов, которые SQLAlchemy, очевидно, хочет иметь), и результат правильно сгруппирован):

SELECT anon_1.id AS anon_1_id, anon_1.name AS anon_1_name, anon_1.fk_test3 AS anon_1_fk_test3, anon_1.linked AS anon_1_linked, anon_1.linked AS linked 
FROM (
   SELECT test.id AS id, test.name AS name, test.fk_test3 AS fk_test3, CASE WHEN (anon_2.id = 87799534) THEN 'true' ELSE 'false' END AS linked 
   FROM test LEFT OUTER JOIN (SELECT test3.id AS id, test3.fk_testvalue AS fk_testvalue 
   FROM test3)
   AS anon_2 ON anon_2.fk_testvalue = test.id ORDER BY linked DESC
)
AS anon_1 GROUP BY anon_1.id

Я тестировал его в phpmyadmin, гдеон дал мне, как и ожидалось, столбец идентификатора (для идентификатора объекта orm), затем дополнительные столбцы SQL_Alchemy, по-видимому, там и связанный столбец.Пока все хорошо.

Теперь мои ожидаемые возвращаемые значения будут такими же, как и в исходном несортированном несгруппированном запросе:

A tuple: 'test' orm object (anon_1.id column), 'true'/'false' value (linked column)

Фактическое возвращаемое значение нового отсортированного / сгруппированногоТем не менее, запрос (исходный запрос действительно возвращает преобразование перед применением приведенного выше кода): только 'test' orm object

Почему это так и как я могу это исправить?

Извинитемне, если такой подход оказывается несколько ошибочным.На самом деле я хочу, чтобы исходный запрос был просто отсортирован, а затем сгруппирован, не касаясь возвращаемых значений.Как вы можете видеть выше, моя попытка была снова «восстановить» дополнительное возвращаемое значение, но это не сработало.Что мне делать вместо этого, если этот подход в корне неверен?

Объяснение использования подзапроса:

Смысл всего подзапроса состоит в том, чтобы заставить SQLAlchemy выполнить этозапросите отдельно в качестве первого шага.

Я хочу сначала упорядочить результаты, а затем сгруппировать упорядоченные результаты .Это кажется трудным сделать правильно за один шаг (при попытке вручную с SQL у меня возникли проблемы с объединением порядка и группы в один шаг, как я хотел).

Поэтому я не просто упорядочиваю, группирую, ноСначала я заказываю, затем подзапрашиваю его, чтобы убедиться, что шаг заказа действительно выполнен первым, а затем группирую его.

Судя по ручным тестам PHPMyAdmin с сгенерированным SQL, это, кажется, работает нормально.Фактическая проблема заключается в том, что исходный запрос (который теперь заключен в подзапрос, о котором вы были сбиты с толку) имел добавленный столбец, и теперь, оборачивая его как подзапрос, этот столбец удаляется из общего результата.И моя попытка записать его во внешнюю упаковку не удалась.

1 Ответ

1 голос
/ 13 декабря 2011

Было бы намного лучше, если бы вы приводили примеры. Я не знаю, находятся ли эти столбцы в отдельных таблицах или нет. Просто глядя на ваш первый абзац, я бы сделал что-то вроде этого:

a = session.query(Table1, Table2.column).\
    join(Table2, Table1.foreign_key == Table2.id).\
    filter(...).group_by(Table2.id).order_by(Table1.property.desc()).all()

Я не знаю точно, что вы пытаетесь сделать, так как мне нужно взглянуть на вашу настоящую модель, но она должна выглядеть примерно так, возможно, таблицы / objs перевернуты или больше фильтров.

...