- 播放器(ID INTEGER PRIMARY KEY,姓名TEXT,性别文字,年龄整数)
- 分数(ID INTEGER PRIMARY KEY,分数TEXT,日期DATE,时间)
- 链接(Player_ID,Score_ID)
我有一个我正在制作的蛇游戏的数据库,如果获得高分(保存了20个最高分),程序会要求用户输入其详细信息以将其保存在此数据库中,但是如果相同的玩家达到它在数据库中重复得分很高,它有一个不同的主键。我怎样才能解决这个问题?如何从播放器表和分数表中读取数据以显示其数据。或者如果我只想显示一个玩家的分数。这就是我到目前为止所做的:
import sqlite3
import time
import random
connection = sqlite3.connect('Test1.db')
cursor = connection.cursor()
def create_Player_Table():
cursor.execute('CREATE TABLE IF NOT EXISTS Player (ID INTEGER PRIMARY
KEY, Name TEXT, Gender TEXT, Age INTEGER)')
def Insert_Player():
ID = cursor.lastrowid
Name = input("Enter name: ")
Gender = input("Enter gender: ")
Age = input("Enter age: ")
cursor.execute("INSERT INTO Player (ID, Name, Gender, Age) VALUES (?, ?, ?, ?)",
(ID, Name, Gender, Age))
connection.commit()
Player_ID = cursor.lastrowid
return Player_ID
def create_Scores_Table():
cursor.execute('CREATE TABLE IF NOT EXISTS Scores (ID INTEGER PRIMARY KEY, Score TEXT, Date DATE, Time TIME)')
def Insert_Score():
ID = cursor.lastrowid
Score = random.randint(1,100000)
Date = time.strftime("%d/%m/%y")
Time = time.strftime("%X")
cursor.execute("INSERT INTO Scores (ID, Score, Date, Time) VALUES (?, ?, ?, ?)",
(ID, Score, Date, Time))
connection.commit()
Score_ID = cursor.lastrowid
return Score_ID
def create_Link_Table():
cursor.execute('CREATE TABLE IF NOT EXISTS Link (Player_ID, Score_ID, FOREIGN KEY (Player_ID) REFERENCES Player (ID), FOREIGN KEY (Score_ID) REFERENCES Scores (ID))')
def Insert_IDs():
cursor.execute("INSERT INTO Link (Player_ID, Score_ID) VALUES (?, ?)",(Player_ID, Score_ID))
connection.commit()
create_Player_Table()
create_Scores_Table()
create_Link_Table()
Player_ID = Insert_Player()
Score_ID = Insert_Score()
Insert_IDs()
答案 0 :(得分:0)
或许完成你想要的第一个阶段是了解如何加入表格。这个的核心是链接表。
因此,您首先从链接表中获取所有行以及链接(相关)数据。
以下表格假设如下: -
因此,以下方法可以做到这一点: -
SELECT * FROM Link JOIN Scores ON Score_ID = Scores.ID JOIN Player ON Player_ID = Player.id
哪会产生: -
我认为上面的答案
如何从播放器表和分数表中读取以显示它 数据
添加WHERE Player.id = 2
会将结果限制为播放器2,例如
SELECT * FROM Link JOIN Scores ON Score_ID = Scores.ID JOIN Player ON Player_ID = Player.id WHERE Player.id = 2
我认为这回答
如果我只想显示一名球员的得分。
如果获得高分(保存20个最高分),则实现该程序 要求用户输入其详细信息以将其保存在此数据库中,但是 如果同一玩家获得高分,则在数据库中重复 它有一个不同的主键。我该如何解决这个问题?
稍微复杂一点,但首先你需要每次播放的前x个分数(为简单起见,示例使用2代表x而不是20)
您可以根据降序( DESC )顺序中的得分列对结果进行排序(排序),从而为玩家 2 获取这些内容 LIMIT 返回x的行( 2 ): -
SELECT score FROM Link JOIN Scores ON Score_ID = Scores.ID JOIN Player ON Player_ID = Player.id WHERE Player.id = 2 ORDER BY Score DESC LIMIT(2);
然而,你会想要最小值(如果大于此值然后加上得分),不幸的是使用SELECT MIN(得分)......将获得最低得分(对于玩家2而言不是100)预期 1100 )
需要复合SELECT,即SELECT MIN(得分),但仅限于播放器的前x分数(即按照之前的选择 - 因此需要选择中的选择)。这将是: -
SELECT MIN(score) FROM (SELECT score FROM Link JOIN Scores ON Score_ID = Scores.ID JOIN Player ON Player_ID = Player.id WHERE Player.id = 2 ORDER BY Score DESC LIMIT(2))
这导致: -
最后阶段是仅提取值,然后在分数大于最小值时插入新行(假设第一个最低分数是要保留的分数)。使用SELECT MIN(score) AS minscore
(即添加AS minscore
)将返回的行重命名为 minscore
而不是MIN(score)
然而,您可以更复杂地使用上述内容来提供SELECT INSERT statement
的值,即它根据SELECT的结果插入数据。您甚至可以使用SQLite日期和时间函数来提供日期和时间值(假设当前时间)。
首先修改上面的日期和时间(refer to - Date And Time Functions进行格式化等)
所以上面可能是: -
SELECT MIN(score) as minscore, date('now') as datenow, time('now') as timenow FROM
(
SELECT score FROM Link
JOIN Scores ON Score_ID = Scores.ID
JOIN Player ON Player_ID = Player.id
WHERE Player.id = 2 /*<<< PLAYER THIS IS FOR */
ORDER BY Score DESC
LIMIT(2) /*<<< Number of scores to consider */
)
这将导致: -
现在需要的是将上述内容限制为仅在minscore小于分数(或分数大于minscore)时返回一行。但是,由于SQLIte确定聚合的方式,WHERE minscore&lt; ?????,必须在选择中包含上面的选择。
另一个复杂性是minscore将被视为TEXT列,因此需要SQLite CAST强制它作为整数使用。 结果是: -
SELECT * FROM (
SELECT MIN(score) as minscore, date('now') as datenow, time('now') as timenow FROM
(
SELECT score FROM Link
JOIN Scores ON Score_ID = Scores.ID
JOIN Player ON Player_ID = Player.id
WHERE Player.id = 2 /*<<< PLAYER THIS IS FOR */
ORDER BY Score DESC
LIMIT(2) /*<<< Number of scores to consider */
)
)
WHERE CAST(minscore AS INT) < 100 /*<<< SCORE to add or not if too small */
几乎就在那里,这将为SELECT INSERT提供数据,最后: -
INSERT INTO Scores (Score, Date, Time)
SELECT * FROM (
SELECT MIN(score) as minscore, date('now') as datenow, time('now') as timenow FROM
(
SELECT score FROM Link
JOIN Scores ON Score_ID = Scores.ID
JOIN Player ON Player_ID = Player.id
WHERE Player.id = 2 /*<<< PLAYER THIS IS FOR */
ORDER BY Score DESC
LIMIT(2) /*<<< Number of scores to consider */
)
)
WHERE CAST(minscore AS INT) < 1200 /*<<< SCORE to add or not if too small */
请注意!然后,您将获得ID( 请注意,ID未指定为列,这是使用ID列的正常方式 )并插入条目进入Link表。 (我相信这也可以通过使用last_insert_rowid()
SQLite函数来完成,但我还没有尝试过。)
P.S。很可能Link表是多余的。也许你可以将相应玩家的id存储在Scores表中(这将简化上述内容。)