peewee自我引用多对多设计和查询问题

时间:2018-04-05 19:49:52

标签: python peewee

我是Python和peewee的新手,这是我在这里的第一篇文章。

另外,我几乎失明了,请原谅任何错别字:)

在对peewee文档进行stydying并搜索此处和其他地方的许多帖子之后, 我仍然对自我指涉,多对多设计如何在小便中起作用存在疑问。

我的目标是查询体育数据库。最后的代码完成了大部分工作,但有两个问题仍未解决(见下文)。

编辑:我解决了以下关于特定锦标赛过滤的问题#1(我将很快发布更新的程序)。

编辑#2:我会把它拿回来!经过进一步测试,我意识到我的#1解决方案不起作用:(

编辑#3:我终于回答了我自己的问题:) 所以...我在声明中修正了一些拼写错误 下面的问题(在表格中)
我将在答案中发布解决方案。

问题陈述

以下是测试数据表(表格最终将包含更多字段)

        Tournaments
+------------+------------+
| tournament | tournament |
|    id      |    name    |  
+------------+------------+
|    101     | US Open    |
|    102     | US Closed  |
+------------+------------+

      Players
+--------+--------+
| player | player |
|   id   |  name  |
+--------+--------+
|    1   | John   |
|    2   | Tony   |
|    3   | Ken    |
|    4   | George |
+--------+--------+

               Matches
+------------+--------+-------+-------+
| tournament | winner | loser |       |
|     id     |   id   |  id   | event |
+------------+--------+-------+-------+
|    101     |   1    |   4   | Semis |
|    101     |   2    |   3   | Semis |
|    101     |   1    |   2   | Final |
|    102     |   1    |   2   | Semis |
|    102     |   3    |   4   | Semis |
|    102     |   1    |   3   | Final |
+------------+--------+-------+-------+

期望的结果是显示玩家1的胜利 美国封闭锦标赛(pid = 1,tid = 102):

+----------+------------+----------+
| Loser id | Loser name |  Event   |
+----------+------------+----------+
|    2     |   Tony     |  Semis   |
|    3     |   Ken      |  Final   |
+----------+------------+----------+

1 个答案:

答案 0 :(得分:1)

我的回答涵盖了原始要求,并在结果表中添加锦标赛信息。

以下是程序输出,后面是完整的程序。

程序输出

                 John's wins in the US Open
event      w_pid  tname      pid    id    l_pid  pname      tid
-------  -------  -------  -----  ----  -------  -------  -----
Semis          1  US Open      4     1        4  George     101
Final          1  US Open      2     3        2  Tony       101
                 John's wins in the US Closed
event      w_pid  tname        pid    id    l_pid  pname      tid
-------  -------  ---------  -----  ----  -------  -------  -----
Semis          1  US Closed      2     4        2  Tony       102
Final          1  US Closed      3     6        3  Ken        102

解决方案

from peewee import *
from pprint import pprint
import tabulate

db = SqliteDatabase('app.db')

class BaseModel(Model):
    class Meta:
        database = db

class Tournament(BaseModel):
    tid       = IntegerField(primary_key=True)
    tname     = CharField()

class Player(BaseModel):
    pid   = IntegerField(primary_key=True)
    pname = CharField()

class Match(BaseModel):
    w_pid = ForeignKeyField(Player) # Winner pid
    l_pid = ForeignKeyField(Player) # Loser pid
    tid   = ForeignKeyField(Tournament)
    event = CharField()

db.drop_tables([Player, Match, Tournament])
db.create_tables([Player, Match, Tournament])

# ----- Tournaments
Tournament.create(tid=101, tname="US Open")
Tournament.create(tid=102, tname="US Closed")

# ----- Players
Player.create(pid=1, pname="John")
Player.create(pid=2, pname="Tony")
Player.create(pid=3, pname="Ken")
Player.create(pid=4, pname="George")

# ----- US Open Matches
Match.create(tid=101, w_pid=1, l_pid=4, event="Semis")
Match.create(tid=101, w_pid=2, l_pid=3, event="Semis")
Match.create(tid=101, w_pid=1, l_pid=2, event="Final")

# ----- US Closed Matches
Match.create(tid=102, w_pid=1, l_pid=2, event="Semis")
Match.create(tid=102, w_pid=3, l_pid=4, event="Semis")
Match.create(tid=102, w_pid=1, l_pid=3, event="Final")

def show_wins(tid, pid):
    Winner = Player.alias()
    wins = (Player
        .select(Player, Match, Tournament)
        .join(Match, on=(Player.pid == Match.l_pid))
        .join(Tournament, on=(Tournament.tid == Match.tid))
        .where(Tournament.tid == tid)
        .switch(Winner)
        .join(Winner, on=(Winner.pid == Match.w_pid))
        .where(Winner.pid == pid)
        .dicts()
    )
    header = wins[0].keys()
    rows =  [x.values() for x in wins]
    print(tabulate.tabulate(rows, header))

print("                 John's wins in the US Open")
show_wins(101, 1)

print("                 John's wins in the US Closed")
show_wins(102, 1)

db.close()