2

sqlalchemy-0.7 に Date 列を持つクラスがあります。column_propertyなど、年を取得して簡単にフィルター処理できる類似のものを使用できますか? どのように書きますか?

IE、私がしたい(宣言構文):

class Foo(Base):
    id   = Column(Integer, primary_key=True)
    date = Column(Date(), nullable=False)
    year = column_property(something here)

# later on
q = session().query(Foo).filter_by(year=2011)
4

1 に答える 1

5

確かにそのようなプロパティを定義できます:

year = column_property(extract('year', date))

でも、本当に必要ですか?フィルター条件を書き換えることで、そのようなプロパティを定義せずに年でフィルター処理できます。

query(Foo).filter(extract('year', Foo.date)==2011)

アップデート

このソリューションは単純に見えますが、欠点もあります。WHERE 句のこのような条件では、日付フィールドにインデックスが使用されません。行数が多く、条件の選択性が高いと、パフォーマンスに大きな影響を与えます。したがって、FULL TABLE SCAN の代わりに RANGE INDEX SCAN を引き起こす条件を書き直すことができます (Simon のコメントで提案されているように):

start = datetime.date(year, 1, 1)
end = datetime.date(year, 12, 31)
query(Foo).filter(Foo.date.between(start, end))

このような動作を持つプロパティを定義することも可能です。コンパレータを再定義するだけです:

class YearComparator(ColumnProperty.Comparator):
    def __eq__(self, year):
        if isinstance(year, int):
            column = self.prop.columns[0].get_children()[0].expr
            start = datetime.date(year, 1, 1)
            end = datetime.date(year, 12, 31)
            return column.between(start, end)
        else:
            # It can be a column or exression which we can't handle such way
            return ColumnProperty.Comparator.__eq__(self, year)
    # __lt__, __gt__ etc. are very similar to __eq__

def year_property(date_column, **kwargs):
    kwargs.setdefault('comparator_factory', YearComparator)
    return column_property(extract('year', date_column), **kwargs)

class Foo(Base):
    __tablename__ = 'Foo'
    id = Column(Integer, primary_key=True)
    date = Column(Date, index=True)
    year = year_property(date)
于 2011-04-05T07:26:14.540 に答える