2015-01-22 3 views
3

Я хотел бы создать запрос с вложенным SELECT с использованием sqlalchemy, но я не могу получить ожидаемый результат.Вложенный SELECT с использованием sqlalchemy

Я, конечно, упростил следующий запрос, поэтому он будет легко понятен для этого сообщения.

Вот запрос, я хотел бы построить:

SELECT pear_table.size, 
     (SELECT MIN(apple.apple_date) 
     FROM apple 
     WHERE apple_id = pear_table.pear_id) apple_min, 
     (SELECT max(lemon.lemon_date) 
     FROM lemon 
     WHERE lemon_id = pear_table.pear_id) lemon_max 
FROM 
    (SELECT pear_id 
    FROM pear 
    WHERE pear_color = 'green') pear_table 

Обратите внимание, что я использую «pear_id» в обоих моих подзапросов. Этот запрос хорошо работает при использовании в качестве строки.

Теперь я пытаюсь построить его с помощью SQLAlchemy:

APPLE = wrapper.getMapper('apple') 
LEMON = wrapper.getMapper('lemon') 
PEAR = wrapper.getMapper('pear') 

pear_table = select([PEAR.apple_id]) 
pear_table.append_whereclause(PEAR.pear_color == 'green') 

apple_min = select([func.min(APPLE.apple_date).label('apple_min')]) 
apple_min.append_whereclause(APPLE.apple_id == pear_table.pear_id) 

lemon_max = select([func.min(LEMON.apple_date).label('lemon_max')]) 
lemon_max.append_whereclause(LEMON.lemon_id == pear_table.pear_id) 

main_query = select([pear_table.c.pear_id, 
        apple_min.c.apple_min, 
        lemon_max.c.lemon_max]) 

А вот что SQLAlchemy построить с этим кодом:

SELECT pear_table.size, 
     apple_min, 
     lemon_max 
FROM 
    (SELECT pear_id 
    FROM pear 
    WHERE pear_color = 'green') pear_table, 
    (SELECT MIN(apple.apple_date) 
    FROM apple 
    WHERE apple_id = pear_table.pear_id) apple_min, 
    (SELECT max(lemon.lemon_date) 
    FROM lemon 
    WHERE lemon_id = pear_table.pear_id) lemon_max 

Проблема заключается в том, что «pear_id» недостижим мои 2 подзапросов «apple» и «lemon», потому что sqlalchemy помещает подзапросы в предложение FROM.

Я пытался исправить мою проблему, используя коррелируют вариант:

. 
apple_min = select([func.min(APPLE.apple_date).label('apple_min')]).correlate(None) 
. 
lemon_max = select([func.min(LEMON.apple_date).label('lemon_max')]).correlate(None) 
. 

Вот что я получаю:

SELECT pear_table.size, 
     apple_min, 
     lemon_max 
FROM 
    (SELECT pear_id 
    FROM pear 
    WHERE pear_color = 'green') pear_table, 
    (SELECT MIN(apple.apple_date) 
    FROM apple, 
     (SELECT pear_id 
     FROM pear 
     WHERE pear_color = 'green') 
    WHERE apple_id = pear_table.pear_id) apple_min, 
    (SELECT max(lemon.lemon_date) 
    FROM lemon, 
     (SELECT pear_id 
     FROM pear 
     WHERE pear_color = 'green') 
    WHERE lemon_id = pear_table.pear_id) lemon_max 

Это дублирует 'FROM pear_id ...', и я не» t хочу дублировать запросы по очевидным причинам производительности.

  • Я что-то не так?
  • Есть ли лучший способ построить мой запрос?
  • Является ли sqlalchemy позвольте мне построить способ, которым я хочу?
  • Есть ли способ разместить подзапросы непосредственно в главном предложении «SELECT»?

В настоящее время я использую sqlalchemy 0.4, но я пробовал то же самое с 0,8, и результат тот же.

ответ

7

Попробуйте это вместо того, чтобы (ключ использовать Scalar Selects):

pear_table = (
    select([PEAR.pear_id]) 
    .where(PEAR.pear_color == 'green') 
) 

apple_min = (
    select([func.min(APPLE.apple_date).label('apple_min')]) 
    .where(APPLE.apple_id == pear_table.c.pear_id) 
).as_scalar() 

lemon_max = (
    select([func.min(LEMON.lemon_date).label('lemon_max')]) 
    .where(LEMON.lemon_id == pear_table.c.pear_id) 
).as_scalar() 

main_query = select([pear_table.c.pear_id, apple_min, lemon_max]) 
print(main_query) 
+0

Спасибо, что это именно то, что я искал! – Schminitz

Смежные вопросы