使用sqlalchemy嵌套SELECT

Sch*_*itz 6 python sqlalchemy

我想使用sqlalchemy创建一个嵌套SELECT的查询,但我无法获得预期的结果.

我当然简化了以下查询,因此这篇文章很容易理解.

这是我想要构建的查询:

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
Run Code Online (Sandbox Code Playgroud)

请注意,我在两个子查询中都使用'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])
Run Code Online (Sandbox Code Playgroud)

以下是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
Run Code Online (Sandbox Code Playgroud)

问题是我的2个子查询'apple'和'lemon'无法访问'pear_id',因为sqlalchemy将子查询放在'FROM'子句中.

我尝试使用correlate选项修复我的问题:

.
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)
.
Run Code Online (Sandbox Code Playgroud)

这是我得到的:

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
Run Code Online (Sandbox Code Playgroud)

这复制了'FROM pear_id ...',出于明显的性能原因,我不希望重复查询.

  • 难道我做错了什么?
  • 有没有更好的方法来构建我的查询?
  • sqlalchemy允许我构建我想要的方式吗?
  • 有没有办法将子查询直接放在主"SELECT"子句中?

我目前正在使用sqlalchemy 0.4,但我用0.8尝试了同样的事情,结果是一样的.

van*_*van 10

试试这个(关键是使用标量选择):

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)
Run Code Online (Sandbox Code Playgroud)