使用 sqlalchemy 嵌套 SELECT
Nested SELECT using sqlalchemy
我想使用 sqlalchemy 创建嵌套 SELECT 的查询,但无法获得预期的结果。
当然,我简化了以下查询,因此对于这个 post。
这是我要构造的查询:
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
问题是我的 2 个子查询 'apple' 和 'lemon' 无法访问 'pear_id',因为 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 ...',出于明显的性能原因,我不想重复查询。
- 我是不是做错了什么?
- 是否有更好的方法来构造我的查询?
- sqlalchemy 允许我按照我想要的方式构建吗?
- 有没有办法将子查询直接放在主 'SELECT' 子句中?
我目前使用的是 sqlalchemy 0.4,但我在 0.8 上尝试了同样的操作,结果是一样的。
试试这个(关键是使用 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)
我想使用 sqlalchemy 创建嵌套 SELECT 的查询,但无法获得预期的结果。
当然,我简化了以下查询,因此对于这个 post。
这是我要构造的查询:
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
问题是我的 2 个子查询 'apple' 和 'lemon' 无法访问 'pear_id',因为 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 ...',出于明显的性能原因,我不想重复查询。
- 我是不是做错了什么?
- 是否有更好的方法来构造我的查询?
- sqlalchemy 允许我按照我想要的方式构建吗?
- 有没有办法将子查询直接放在主 'SELECT' 子句中?
我目前使用的是 sqlalchemy 0.4,但我在 0.8 上尝试了同样的操作,结果是一样的。
试试这个(关键是使用 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)