SQLAlchemy创建标量子查询列,并与外部子查询表中的列进行比较

时间:2012-03-27 18:54:04

标签: sqlalchemy subquery scalar-subquery

我正在尝试编写一个创建标量子查询列的查询,该列引用一个兄弟列,该列是子查询表中的一列。我把我正在尝试的一个简单的例子放在一起,虽然我实际上使用它的方式有点复杂。

Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()

class A(Base):
    __tablename__ = "TestA"
    id = Column('id', Integer, primary_key=True)
    name = Column('name', String).label('name')
    metric = Column('metric', Integer).label('metric')
    increment_day = Column('increment_day', Date).label('increment_day')

class B(Base):
    __tablename__ = "TestB"
    id = Column('id', Integer, primary_key=True)
    name = Column('name', String).label('name')
    metric = Column('metric', Integer).label('metric')
    increment_day = Column('increment_day', Date).label('increment_day')

class C(Base):
    __tablename__ = "TestC"
    c_id = Column('c_id', Integer, primary_key=True)
    c_metric = Column('c_metric', Integer)
    c_increment_day = Column('c_increment_day', Date)

a_query = session.query(*[A.id, A.name, A.metric, A.increment_day,]).filter(A.increment_day=='2012-01-01')
b_query = session.query(*[B.id, B.name, B.metric, B.increment_day,]).filter(B.increment_day=='2012-01-02')
inner_query = a_query.union_all(b_query).subquery('res')
outer_query = session.query(*[inner_query.c.increment_day, 
                              func.sum(inner_query.c.metric)])
c_select = session.query(*[func.sum(C.c_metric),])\
                  .filter(C.c_increment_day==inner_query.c.increment_day)
outer_query = outer_query.add_column(c_select.as_scalar())

生成如下所示的SQL:

SELECT res.increment_day
     , sum(res.metric) AS sum_1
     , ( SELECT sum(`TestC`.c_metric) AS sum_2
           FROM `TestC`,
              , ( SELECT anon_2.name AS name
                       , anon_2.metric AS metric
                       , anon_2.increment_day AS increment_day
                    FROM ( SELECT `TestA`.id AS `TestA_id`
                                , name AS name
                                , metric AS metric
                                , increment_day AS increment_day
                             FROM `TestA`
                            WHERE increment_day = '2012-01-01'
                            UNION ALL 
                           SELECT `TestB`.id AS `TestB_id`
                                , name AS name
                                , metric AS metric
                                , increment_day AS increment_day
                             FROM `TestB`
                            WHERE increment_day = '2012-01-02'
                         ) AS anon_2
                ) AS res
          WHERE `TestC`.c_increment_day = res.increment_day
       ) AS anon_1
  FROM ( SELECT anon_2.name AS name
              , anon_2.metric AS metric
              , anon_2.increment_day AS increment_day
           FROM ( SELECT `TestA`.id AS `TestA_id`
                       , name AS name
                       , metric AS metric
                       , increment_day AS increment_day
                    FROM `TestA`
                   WHERE increment_day = '2012-01-01'
                   UNION ALL 
                  SELECT `TestB`.id AS `TestB_id`,
                       , name AS name
                       , metric AS metric
                       , increment_day AS increment_day
                    FROM `TestB`
                   WHERE increment_day = '2012-01-02'
                ) AS anon_2
       ) AS res

我的问题是,我如何设置我的查询,以便在标量列查询中不重复'res'子查询,以便查询看起来像:

SELECT res.increment_day
     , sum(res.metric) AS sum_1
     , ( SELECT sum(`TestC`.c_metric) AS sum_2
           FROM `TestC`
          WHERE `TestC`.c_increment_day = res.increment_day
       ) AS anon_1
  FROM ( SELECT anon_2.name AS name
              , anon_2.metric AS metric
              , anon_2.increment_day AS increment_day
           FROM ( SELECT `TestA`.id AS `TestA_id`
                       , name AS name
                       , metric AS metric
                       , increment_day AS increment_day
                    FROM `TestA`
                   WHERE increment_day = '2012-01-01'
                   UNION ALL 
                  SELECT `TestB`.id AS `TestB_id`,
                       , name AS name
                       , metric AS metric
                       , increment_day AS increment_day
                    FROM `TestB`
                   WHERE increment_day = '2012-01-02'
                ) AS anon_2
       ) AS res

1 个答案:

答案 0 :(得分:2)

直到0.8,你必须明确地告诉Query你如何将它与它之外的SELECT语句联系起来:

c_select = session.query(*[func.sum(C.c_metric),])\
                  .filter(C.c_increment_day==inner_query.c.increment_day).correlate(inner_query)