在sqlalchemy中,如何获得一个匹配表中所有行的查询,以使另一个表中没有行链接到它?

2024-10-01 02:19:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个表,“event”和“event_exception”。表“event”有一个(boolean)列“regular”,指示事件是否每年定期发生。表“event_exception”有一列“event_id”、一列“year”和一列(boolean)列“occurrents”。在

数据的解释方式如下:

  • 有些事件每年都有规律地发生,但有时却不经常发生,这是由“事件”行编码的事件.常规==True”和带有“event”的“event_exception”行_发生异常==False“对于每一个例外事件被省略的年份。在
  • 有些事件不经常发生,但有时却异常地发生。这是由“event”行编码的事件.常规==False“和一个带有“event”的“event_exception”行_发生异常==True“对于事件异常发生的每一年。在

如何编写与今年将发生的所有事件匹配的查询?在

我猜大概是

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_内使用。在


Tags: andeventidtrue编码exception事件filter
2条回答

我不确定答案,我只想指出一些事情,因为我最近在sqlalchemy下使用布尔查询时遇到了一些问题。。。在

  • 您应该将布尔值比较为'==True'和'==False'。MySQL将Boolean存储为1/0,但是PostgreSQL和其他一些存储为true/false,Python也是如此。SqlAlchemy可以根据需要进行转换,但是当您查看其他人的代码时。。。好吧,这看起来像一个整数比较,而不是一个布尔。对其他将来不得不看这个的人来说会更容易。

  • 根据SQL存储引擎和列默认值,您可能无法获得所需的结果。如果集合中允许空值,则比较将不匹配。您将通过以下搜索获得所需的结果:

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

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

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

在第一段代码中,我们搜索不为True的项,这些项将同时为False和NULL。regular != True的结果集只包含False项;regular IS NOT True的结果集包含False和{}

在第二位代码中,数据库将在比较之前将Null值合并为False。在

你可能不需要做这些比较,但如果你做了这些比较,你的结果看起来不对,这可能就是原因。在

如果没有GROUP BY,则不能使用HAVING。不管怎样,在这种情况下这两个都不是必需的,需要的是EXISTS。假设您已经为Event.exceptions定义了一个SQLAlchemy关系,下面的表达式应该可以工作:

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:

^{pr2}$

编辑:第一个条件应该使用NOT EXISTS

相关问题 更多 >