2017-04-10 78 views
1

實現標題幾乎等於How to use a labelled column in sqlalchemy filter?我相信這是一個單獨的問題。在union'd SQLAlchemy查詢中按標籤列進行過濾

,極大地簡化了我的問題:假如我有兩個疑問,每個返回我想要的結果的一個子集,我工會一起:

initial_task = "initial_task" 
scheduled_task = "scheduled_task" 

initial = session.query(Task.task_id, 
         User.signup_date.label('due_date'), 
         literal(initial_task).label('type'))\ 
       .join(Task.user) 

schedule = session.query(Task.task_id, 
         Schedule.due_date.label('due_date'), 
         literal(scheduled_task).label('type'))\ 
        .join(Task.schedule) 

tasks = initial.union_all(schedule) 

而且是明確的:我知道這個例子可以改寫沒有工會;我的實際用例有五個單獨的查詢,除了這個正常格式的強制結果之外幾乎沒有任何共同之處。

如何過濾tasks以僅包含2017年4月1日之後到期的任務?從概念上講,是這樣的:

tasks.filter(tasks.c.due_date >= datetime(2017, 4, 1)) 

的主要問題是我無法弄清楚如何參考due_date列在一般的方式。一切我從文檔嘗試似乎談論低層API,並在ORM層導致:

'Query' object has no attribute 'c' 

回答

1

Query.union_all()方法產生一個新的Query實例,這是由生產的CompoundSelect有點不同正如你所指出的那樣,sql.expression.union_all()構造。你可以使用literal_column()過濾查詢:

In [18]: tasks.filter(literal_column('due_date') >= datetime(2017, 4, 1)) 
Out[18]: <sqlalchemy.orm.query.Query at 0x7f1d2e191b38> 

In [19]: print(_) 
SELECT anon_1.task_id AS anon_1_task_id, anon_1.due_date AS anon_1_due_date, anon_1.type AS anon_1_type 
FROM (SELECT task.id AS task_id, user.signup_date AS due_date, ? AS type 
FROM task JOIN user ON task.id = user.task_id UNION ALL SELECT task.id AS task_id, schedule.due_date AS due_date, ? AS type 
FROM task JOIN schedule ON task.id = schedule.task_id) AS anon_1 
WHERE due_date >= ? 

在另一方面,你可以只單獨過濾工會的部分在各自日期列。

最後,你可以換你的工會在子查詢,如果這是更接近你的實際目標(由簡單的例子是隱藏的):

In [26]: tasks_sq = tasks.subquery() 

In [27]: session.query(tasks_sq).\ 
    ...:  filter(tasks_sq.c.due_date >= datetime(2017, 4, 1)) 
Out[27]: <sqlalchemy.orm.query.Query at 0x7f1d2e1d4828> 

In [28]: print(_) 
SELECT anon_1.task_id AS anon_1_task_id, anon_1.due_date AS anon_1_due_date, anon_1.type AS anon_1_type 
FROM (SELECT anon_2.task_id AS task_id, anon_2.due_date AS due_date, anon_2.type AS type 
FROM (SELECT task.id AS task_id, user.signup_date AS due_date, ? AS type 
FROM task JOIN user ON task.id = user.task_id UNION ALL SELECT task.id AS task_id, schedule.due_date AS due_date, ? AS type 
FROM task JOIN schedule ON task.id = schedule.task_id) AS anon_2) AS anon_1 
WHERE anon_1.due_date >= ? 
相關問題