2014-09-30 2 views
1

SQLAlchemy에 동일한 보조 테이블에 대해 여러 개의 관계가있는 클래스가 있습니다. 다음과 같이 보입니다.SQLAlchemy : 동일한 테이블에 대한 여러 관계에 의한 계산 및 정렬

class Job(Base): 
    __tablename__ = 'jobs' 
    id = Column(Integer, primary_key=True) 
    tasks_queued = relationship("Task", lazy="dynamic", 
     primaryjoin="(Task.state == 'queued') & (Task.job_id == Job.id)") 
    tasks_running = relationship("Task", lazy="dynamic", 
     primaryjoin="(Task.state == 'running') & (Task.job_id == Job.id)") 
    tasks_done = relationship("Task", lazy="dynamic", 
     primaryjoin="(Task.state == 'done') & (Task.job_id == Job.id)") 
    tasks_failed = relationship("Task", lazy="dynamic", 
     primaryjoin="(Task.state == 'failed') & (Task.job_id == Job.id)") 

class Task(Base): 
    __tablename__ = 'tasks' 
    id = Column(Integer, primary_key=True) 
    job_id = Column(Integer, ForeignKey("jobs.id")) 
    state = Column(String(8), nullable=False, default='queued') 
    job = relationship("Job") 

작업에 0 개 이상의 작업이 있습니다. 태스크는 "대기 중", "실행 중", "완료"또는 "실패"의 4 가지 상태 중 하나를 가질 수 있습니다. 작업을 쿼리 할 때, 각 작업에 대기중인 작업, 실행중인 작업, 완료된 작업 및 실패한 작업의 수를 국가별로 나눠보고 싶습니다. 나는 또한 그 수에 따라 출력을 분류 할 수 있기를 원한다. 최대한 빨리 하나 개 이상의 관계로 그 확장을 시도로서, 일이 어두운 얻을 시작, 그러나

session.query(Job, func.count(Job.tasks_queued).label("t_queued")).\ 
outerjoin(Job.tasks_queued).group_by(Job).order_by("t_queued ASC").all() 

: 인터넷 검색을 조금 후

, 나는 하나 개의 관계를 그렇게하는 방법을 발견 :

sqlalchemy.exc.OperationalError: (OperationalError) ambiguous column name: tasks.state 'SELECT jobs.id AS jobs_id, count(tasks.state = ? AND tasks.job_id = jobs.id) AS t_queued, count(tasks.state = ? AND tasks.job_id = jobs.id) AS t_running \nFROM jobs LEFT OUTER JOIN tasks ON tasks.state = ? AND tasks.job_id = jobs.id LEFT OUTER JOIN tasks ON tasks.state = ? AND tasks.job_id = jobs.id GROUP BY jobs.id ORDER BY t_queued ASC' ('queued', 'running', 'queued', 'running') 

그래서 어떻게 든 SQLAlchemy의 그쪽으로 알려줄 필요가 :

session.query(Job, func.count(Job.tasks_queued).label("t_queued"), 
    func.count(Job.tasks_running).label("t_running")).\ 
outerjoin(Job.tasks_queued).\ 
outerjoin(Job.tasks_running).group_by(Job).order_by("t_queued ASC").all() 

이 오류가 발생합니다 첫 번째 카운트는 첫 번째 조인을, 두 번째 조인은 두 번째 조인을 나타냅니다. 순수한 SQL에서는 join 된 테이블에 ad-hoc 별칭을 지정하고 count() 함수의 테이블 이름 대신 해당 별칭을 참조합니다. SQLAlchemy에서 어떻게 할 수 있습니까? 당신이 aliases sqlalchemy로 사용할 수 있습니다

답변

1

같은 방법 :

a_q = aliased(Task) 
a_r = aliased(Task) 
a_d = aliased(Task) 
a_f = aliased(Task) 
qry2 = (session.query(Job, 
         func.count(a_q.id.distinct()).label("t_queued"), 
         func.count(a_r.id.distinct()).label("t_running"), 
         func.count(a_d.id.distinct()).label("t_done"), 
         func.count(a_f.id.distinct()).label("t_failed"), 
        ) 
     .outerjoin(a_q, Job.tasks_queued) 
     .outerjoin(a_r, Job.tasks_running) 
     .outerjoin(a_d, Job.tasks_done) 
     .outerjoin(a_f, Job.tasks_failed) 
     .group_by(Job) 
     .order_by("t_queued ASC") 

은 당신이 생각하는 count들에 distinct를 추가 할 필요가 있다고 생각합니다.

+0

감사합니다. – guidow

+0

다행. 그러나 호기심에서 벗어난 이유는 무엇입니까? 문제는'my_job.tasks_done.append (Task())'를 따르는 경우 새로운'Task'의'state'를'done'으로 설정하지 않는다는 것입니다. 따라서 제대로 작동하는 관계가 아닙니다. – van

관련 문제