PostgreSQL-提取最大时间戳小于特定日期
我有一个问题试图查询任务。因此,我需要为竞赛平台实现一个评分系统,但是要计算和更新用户的评级,我需要提取用户的最后一个评级(因为表保留了整个历史记录)。
现在,这些是负责此任务的表(我仅保留相关的列):
基于“ ID”的商店竞赛:
CREATE TABLE IF NOT EXISTS contests (
id TEXT NOT NULL,
date_end TIMESTAMP NOT NULL,
PRIMARY KEY (id)
);
存储所有注册特定竞赛的用户:
CREATE TABLE IF NOT EXISTS contest_participants (
username TEXT NOT NULL,
contest_id TEXT NOT NULL,
PRIMARY KEY (username, contest_id),
FOREIGN KEY (contest_id) REFERENCES contests (id)
);
根据他们参与的竞赛存储所有用户的评分在:
CREATE TABLE IF NOT EXISTS contest_ratings (
id INT AUTO_INCREMENT,
contest_id TEXT NOT NULL,
username TEXT NOT NULL,
rating INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (contest_id) REFERENCES contests (id)
);
现在,由于能够一次计算超过1个竞赛评级,因此我无法使用ID
列vonty>竞赛
。
我能找到的最好的选择是在竞赛
中使用date_end
列。基本上,如果我寻找最大data_end
低于当前竞赛(ex:max(date_end)<'current_timestamp'
),我可以找到最后的评分用户。但是我真的不知道该怎么做。
假设我们有以下数据:
--------------------------------------|
contests |
----------------+---------------------|
id | date_end |
----------------+------------------+--|
test-contest-1 | 2022-05-10 15:55:00 |
test-contest-2 | 2022-05-10 17:00:00 |
test-contest-3 | 2022-05-12 17:09:00 |
-----------------------------|
contest_participants |
------------+----------------|
username | contest_id |
------------+----------------|
KeepCoding | test-contest-1 |
TestUser | test-contest-1 |
KeepCoding | test-contest-2 |
KeepCoding | test-contest-3 |
TestUser | test-contest-3 |
-------------------------------------------|
contest_ratings |
----+----------------+------------+--------|
id | contest_id | username | rating |
----+----------------+------------+--------|
1 | test-contest-1 | KeepCoding | 100 |
2 | test-contest-1 | TestUser | 10 |
3 | test-contest-2 | KeepCoding | 200 |
我们要计算test-contest-3
竞赛的评级。为此,我们需要从test-contest-2
竞赛中提取keepscoding
用户的评分,以及test-contest-1 对于
tastuser
用户。
尝试自己解决这个问题,这几乎是我能想到的,但无法正常工作,因为正在为同一用户返回更多评级
列,我只是不知道为什么。
因此,首先,我们需要最大date_end
:
SELECT id, max(date_end) as date_end FROM contests WHERE date_end < 'current_timestamp'
然后提取额定值
SELECT cr.username, cr.rating FROM (...) s JOIN contest_ratings cr ON s.id = cr.id
,然后添加我写的过滤器
SELECT * FROM (...) t JOIN contest_participants cp ON t.username = cp.username AND cp.contest = 'current-contest-id';
(...)我的意思是括号中的上一个查询
I have a problem trying to query a task. So, I need to implement a Rating System for a contest platform, but to calculate and update a user's rating I need to extract the last rating a user had (because the table keeps the entire history).
Now, these are the tables responsible for this task (I left only the relevant columns):
store contests based on "ID":
CREATE TABLE IF NOT EXISTS contests (
id TEXT NOT NULL,
date_end TIMESTAMP NOT NULL,
PRIMARY KEY (id)
);
stores all users who register for a particular contest:
CREATE TABLE IF NOT EXISTS contest_participants (
username TEXT NOT NULL,
contest_id TEXT NOT NULL,
PRIMARY KEY (username, contest_id),
FOREIGN KEY (contest_id) REFERENCES contests (id)
);
stores the rating of all users based on the contests they have participated in:
CREATE TABLE IF NOT EXISTS contest_ratings (
id INT AUTO_INCREMENT,
contest_id TEXT NOT NULL,
username TEXT NOT NULL,
rating INT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (contest_id) REFERENCES contests (id)
);
Now, due to the ability to calculate more than 1 contest rating at a time, I can't use the id
column in contest_ratings
because that can create certain race conditions.
The best option I could find was to use the date_end
column in contests
. Basically, if I look for the maximum data_end
that is lower than the current contest (ex: max(date_end) < 'current_timestamp'
), I can find the last rating of a user. But I really can't figure out how to do that.
Let's say that we have the following data:
--------------------------------------|
contests |
----------------+---------------------|
id | date_end |
----------------+------------------+--|
test-contest-1 | 2022-05-10 15:55:00 |
test-contest-2 | 2022-05-10 17:00:00 |
test-contest-3 | 2022-05-12 17:09:00 |
-----------------------------|
contest_participants |
------------+----------------|
username | contest_id |
------------+----------------|
KeepCoding | test-contest-1 |
TestUser | test-contest-1 |
KeepCoding | test-contest-2 |
KeepCoding | test-contest-3 |
TestUser | test-contest-3 |
-------------------------------------------|
contest_ratings |
----+----------------+------------+--------|
id | contest_id | username | rating |
----+----------------+------------+--------|
1 | test-contest-1 | KeepCoding | 100 |
2 | test-contest-1 | TestUser | 10 |
3 | test-contest-2 | KeepCoding | 200 |
And we want to calculate the rating for the test-contest-3
contest. For that, we need to extract the rating from the test-contest-2
contest for the KeepCoding
user and the rating from test-contest-1
for the TestUser
user.
Trying to solve this by myself, this is pretty much all I could come up with but is not working properly, because is returning more rating
columns for the same user and I just can't figure out why.
So first we want the maximum date_end
:
SELECT id, max(date_end) as date_end FROM contests WHERE date_end < 'current_timestamp'
Then we extract the ratings
SELECT cr.username, cr.rating FROM (...) s JOIN contest_ratings cr ON s.id = cr.id
Then add the filter
SELECT * FROM (...) t JOIN contest_participants cp ON t.username = cp.username AND cp.contest = 'current-contest-id';
Where I wrote (...) I mean the previous query in parentheses
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论