2014-08-28 3 views
3

테이블에 몇 개의 필드를 그룹화하고 그룹을 합산하려고 시도하지만 이중으로 계산됩니다. 다음과 같이GroupBy 및 SQLAlchemy의 합계?

내 모델은 다음과 같습니다 : 내가 사용하고

class CostCenter(db.Model): 
    __tablename__ = 'costcenter' 
    id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
    name = db.Column(db.String) 
    number = db.Column(db.Integer) 

class Expense(db.Model): 

    __tablename__ = 'expense' 
    id = db.Column(db.Integer, primary_key=True, autoincrement=True) 
    glitem_id = db.Column(db.Integer, db.ForeignKey('glitem.id')) 
    glitem = db.relationship('GlItem') 
    costcenter_id = db.Column(db.Integer, db.ForeignKey('costcenter.id')) 
    costcenter = db.relationship('CostCenter') 
    value = db.Column(db.Float) 
    date = db.Column(db.Date) 

: 나는 비용을 인쇄 할 때

expenses=db.session.query(Expense,func.sum(Expense.value)).group_by(Expense.date).filter(CostCenter.id.in_([1,2,3])) 

는 다음 SQL 문을 보여줍니다. 그것은 나에게 맞는 것 같지만 SQL에 익숙하지 않습니다. 문제는 sum_1로 출력하는 값이 여러 번 계산된다는 것입니다. "in statment"항목에 [1] 항목이 있으면 3 가지를 모두 합산합니다. 내가 [1,2]를 가졌다면 3 가지를 모두 합친 다음 두 배로 늘리고, [1,2,3]이 있으면 3 가지를 모두 합하여 3 배로 만듭니다. 왜 그것이 여러 번 세지 모르겠습니다. 이 문제를 어떻게 해결할 수 있습니까?

SELECT expense.id AS expense_id, expense.glitem_id AS expense_glitem_id, expense.costcenter_id AS   expense_costcenter_id, expense.value AS expense_value, expense.date AS expense_date, sum(expense.value) AS sum_1 
FROM expense, costcenter 
WHERE costcenter.id IN (:id_1, :id_2, :id_3) GROUP BY expense.date 

고마워요!

답변

14

여기에 몇 가지 문제가 있습니다. 당신은 옳은 것을 질의하는 것 같지 않습니다. Expense.date별로 그룹화 할 때 Expense 개체를 선택하는 것은 의미가 없습니다. CostCenter와 비용 사이에 조인 조건이 있어야합니다. 그렇지 않으면 행이 복제되고 각 비용 센터마다 계산되지만 둘 사이에는 관계가 없습니다.

귀하의 질의는 다음과 같아야합니다

session.query(
    Expense.date, 
    func.sum(Expense.value).label('total') 
).join(Expense.cost_center 
).filter(CostCenter.id.in_([2, 3]) 
).group_by(Expense.date 
).all() 

을이 SQL 생산 :

from datetime import datetime 
from sqlalchemy import create_engine, Column, Integer, ForeignKey, Numeric, DateTime, func 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import Session, relationship 

engine = create_engine('sqlite://', echo=True) 
session = Session(bind=engine) 
Base = declarative_base(bind=engine) 


class CostCenter(Base): 
    __tablename__ = 'cost_center' 

    id = Column(Integer, primary_key=True) 


class Expense(Base): 
    __tablename__ = 'expense' 

    id = Column(Integer, primary_key=True) 
    cost_center_id = Column(Integer, ForeignKey(CostCenter.id), nullable=False) 
    value = Column(Numeric(8, 2), nullable=False, default=0) 
    date = Column(DateTime, nullable=False) 

    cost_center = relationship(CostCenter, backref='expenses') 


Base.metadata.create_all() 

session.add_all([ 
    CostCenter(expenses=[ 
     Expense(value=10, date=datetime(2014, 8, 1)), 
     Expense(value=20, date=datetime(2014, 8, 1)), 
     Expense(value=15, date=datetime(2014, 9, 1)), 
    ]), 
    CostCenter(expenses=[ 
     Expense(value=45, date=datetime(2014, 8, 1)), 
     Expense(value=40, date=datetime(2014, 9, 1)), 
     Expense(value=40, date=datetime(2014, 9, 1)), 
    ]), 
    CostCenter(expenses=[ 
     Expense(value=42, date=datetime(2014, 7, 1)), 
    ]), 
]) 
session.commit() 

base_query = session.query(
    Expense.date, 
    func.sum(Expense.value).label('total') 
).join(Expense.cost_center 
).group_by(Expense.date) 

# first query considers center 1, output: 
# 2014-08-01: 30.00 
# 2014-09-01: 15.00 
for row in base_query.filter(CostCenter.id.in_([1])).all(): 
    print('{}: {}'.format(row.date.date(), row.total)) 

# second query considers centers 1, 2, and 3, output: 
# 2014-07-01: 42.00 
# 2014-08-01: 75.00 
# 2014-09-01: 95.00 
for row in base_query.filter(CostCenter.id.in_([1, 2, 3])).all(): 
    print('{}: {}'.format(row.date.date(), row.total)) 
: 여기
SELECT expense.date AS expense_date, sum(expense.value) AS total 
FROM expense JOIN cost_center ON cost_center.id = expense.cost_center_id 
WHERE cost_center.id IN (?, ?) GROUP BY expense.date 

간단한 실행 가능한 예제를