1

「event」と「event_exception」の2つのテーブルがあります。テーブル「event」には、イベントが毎年定期的に発生するかどうかを示す(ブール)列「regular」があります。テーブル「event_exception」には、列「event_id」、列「year」、および(ブール)列「occurs」があります。

データは次のように解釈されます。

  • 一部のイベントは毎年定期的に発生しますが、例外的に発生しない場合もあります。これは、「event.regular==True」の「event」行と「event_exception.occurs==False」の「event_exception」行でエンコードされています。イベントが例外的に省略される毎年。
  • 定期的に発生しないイベントもありますが、例外的に発生する場合もあります。これは、イベントが例外的に発生する毎年、「event.regular==False」の「event」行と「event_exception.occurs==True」の「event_exception」行によってエンコードされています。

今年発生するすべてのイベントに一致するクエリを作成するにはどうすればよいですか?

私の推測は次のようなものでした

session.query(Event, EventException).filter(Event.id==EventException.event_id)
.filter(EventException.year==current_year).
filter(or_(
    and_(Event.regular==1, EventException.occurs==0, having(count(EventException)==0)),
    and_(Event.regular==0, EventException==1, having(count(EventException)>0)
))

having、しかし、句が。内で使用できるかどうかはわかりませんand_

4

2 に答える 2

1

HAVINGなしでは使用できませんGROUP BY。とにかく、この場合はどちらも必要ありません。必要なのはですEXISTS。にSQLAlchemy関係がすでに定義されているとするとEvent.exceptions、次の式が機能するはずです。

session.query(Event).filter(or_(
    and_(
        Event.regular == True,
        ~Event.exceptions.any(and_(
            EventException.year == current_year,
            EventException.occurs == False,
        )),
    ),
    and_(
        Event.regular == False,
        Event.exceptions.any(and_(
            EventException.year == current_year,
            EventException.occurs == True,
        )),
    ),
))

次のようなSQLを生成します。

SELECT event.*
FROM event
WHERE
    (
        event.regular = true
        AND NOT EXISTS (
            SELECT 1
            FROM event_exception
            WHERE
                event.id = event_exception.event_id
                AND event_exception.year == :year
                AND event_exception.occurs = false
        )
    )
    OR
    (
        event.regular = false
        AND EXISTS (
            SELECT 1
            FROM event_exception
            WHERE
                event.id = event_exception.event_id
                AND event_exception.year == :year
                AND event_exception.occurs = true
        )
    )

編集:最初の条件はNOT EXISTS代わりに使用する必要があります

于 2012-09-03T00:21:51.157 に答える
1

答えがわからないので、最近sqlalchemyの下でブールクエリに問題があったので、いくつか注意したいだけです...

  • '== True' と '== False' としてブール比較を行う必要があります。MySQL は Boolean を 1/0 として保存しますが、PostgreSQL などは true/false として保存し、Python も同様です。SqlAlchemy は必要に応じて変換しますが、他の人のコードを見ていると、BOOL ではなく INT 比較のように見えます。将来これを見なければならない他の人にとっては、より簡単になります。.

  • SQL ストレージ エンジンと列の既定値によっては、必要な結果が得られない場合があります。セットに NULL 値が許可されている場合、比較は一致しません。次のような検索で、必要な結果が得られます。

    Event.regular.op('IS NOT')(True)

    Event.regular.op('IS')(False)

    sqlalchemy.sql.functions.coalesce( Event.regular , False ) != True sqlalchemy.sql.functions.coalesce( Event.regular , False ) == False

コードの最初のビットでは、True ではない項目を検索します。これは False と NULL の両方になります。の結果セットにはアイテムregular != Trueのみが含まれます。containsおよびFalseの結果セットregular IS NOT TrueFalseNull

コードの 2 番目のビットでは、データベースは比較の前にNull値を結合します。False

これらの比較を行う必要はないかもしれませんが、実行して結果が正しく見えない場合は、おそらくこれが原因です。

于 2012-09-02T19:59:19.433 に答える