选择在其他记录列表中找不到的记录

时间:2016-08-31 13:20:09

标签: ponyorm

方案

玩家参加活动。如果他们要去参加活动,他们应该提供信息。

要解决的问题

如果他们计划参加特定活动,我想选择那些没有提供信息的玩家。

您的目标

作为所使用技术的初学者,我将非常感谢您的验证和建议,以改进我在下面建议的解决方案。

解决方案

技术: python,postgreSQL和Pony ORM

Pony ORM中的实体模型:

class Event(db.Entity):
    _table_ = "event"
    start = Required(date)
    players = Set("Attendance")


class Player(db.Entity):
    _table_ = "player"
    first_name = Optional(str)
    last_name = Required(str)
    phone_number = Required(str)
    email = Required(str)
    events = Set("Attendance")


class Attendance(db.Entity):
    _table_ = "attendance"
    event = Required(Event)
    player = Required(Player)
    status = Required(bool)
    PrimaryKey(event, player)

  1. 获取参加活动时提供信息的玩家列表
  2. 获取不在1中创建的列表中的玩家列表。
  3. 该想法的当前实施:

    players = select(p for p in Player if p not in select(p for p in Player
                     for a in Attendance if p == a.player and a.event == next_event))
    

1 个答案:

答案 0 :(得分:2)

可以重构您的查询以使其更简单。首先,我们可以通过属性访问将内部查询中的PlayerAttendance的显式连接替换为隐式连接:

select(p for p in Player if p not in select(p for p in Player
       for attendance in p.events if attendance.event == next_event))

为了进一步简化查询,我们可以通过编写表达式p.events.event

来使用attribute lifting
select(p for p in Player if p not in select(
       p for p in Player if next_event in p.events.event))

p.events表达式返回一组Attendance条记录。在Pony中,如果您有一个集合实例,则此集合具有其项目的所有属性,当您访问此类属性时,您将获得一组相应项目属性的所有值。表达式p.events.event的值将是与特定播放器链接的所有Event个对象的集合。

简化查询的下一步是将生成器替换为lambda。这样查询看起来会更短:

Player.select(lambda p: p not in Player.select(
    lambda p: next_event in p.events.event))

但如果我们意识到内部查询是不必要的并且重写查询为:

,则可以实现最大的简化。
Player.select(lambda p: next_event not in p.events.event)

我认为这是使用PonyORM

编写此查询的最简洁方法
相关问题