如何限制每个所有者标识在数据库中的行数
How to limit number of rows in a database for each owner id
我需要为 Postgres 创建一个复杂的 SQL 语句,我似乎无法理解,有人能帮我解决这个问题吗?这是我需要的:
我有一个名为 tags
的 table,它是一个存储名称和值的 table,以及拥有标签的用户 ID 和 ID 等信息标签本身。对于此问题的上下文,您只需要了解以下列:
id
: 标签本身的Id (BIGSERIAL)
guild_id
: tag所在公会的id(BIGINT)。一个公会本质上就是一大群用户在一个巨大的房间里,每个tag只关联一个群。
owner_id
: 拥有标签的用户id (BIGINT)。
created_at
:标签创建时间的UTC时间戳(TIMESTAMP)。
我需要允许版主将公会中每个用户的所有多余标签删除到特定限制,首先优先处理较旧的标签。例如,假设这是我的 table:
id | guild_id | owner_id | created_at
----+--------------------+--------------------+----------------------------
14 | 715039810976219206 | 322896727071784960 | 2022-03-30 21:47:36.81417
17 | 715039810976219206 | 600855080962490396 | 2022-03-31 00:57:18.024558
20 | 715039810976219206 | 322896727071784960 | 2022-03-31 01:03:57.586239
21 | 715039810976219206 | 322896727071784960 | 2022-03-31 01:35:13.426953
22 | 715039810976219206 | 322896727071784960 | 2022-04-14 02:02:46.852122
25 | 715039810976219206 | 322896727071784960 | 2022-04-14 02:03:13.559069
26 | 239865610974543234 | 322896727071784960 | 2022-04-14 02:03:18.885876
当版主尝试以 3 的限制和 715039810976219206 的公会执行此功能时,它将执行以下操作:
- 对于
owner_id
列中的每个用户,它将确定他们是否在特定公会 中拥有 3 个或更多标签 。在此示例中,用户 322896727071784960 在公会 715039810976219206. 中拥有超过 3 个标签
- 然后它将继续删除所有标签,直到标签只剩下3个。 重要的是它首先优先删除旧标签。在这种情况下,它将删除标签 14 和 20。这将导致公会 715039810976219206 中的用户 322896727071784960 只剩下 3 个标签.
我已经尝试了一段时间了,如果有帮助的话,这是我到目前为止所得到的:
DELETE FROM tags
WHERE id IN (
SELECT id FROM tags
WHERE guild_id = AND owner_id = ???? ORDER BY created_at DESC
OFFSET
);
(那个????是因为我完全失去了我在做什么)
希望我已经解释清楚,让您能够理解。任何帮助将不胜感激,如果可能的话,对答案的解释将很有帮助。
如果我对你的问题的理解正确,你可以使用 rank() 函数并按 owner_id 对它们进行分组,然后按分区日期排序。然后删除所有排名高于 3 的记录。
DELETE FROM tags WHERE id in (
SELECT id FROM
(
SELECT id,
owner_id,
rank() over (partition by owner_id order by created_at desc) as rnk
FROM tags
) as t
WHERE t.rnk > 3
);
SELECT * FROM tags
我需要为 Postgres 创建一个复杂的 SQL 语句,我似乎无法理解,有人能帮我解决这个问题吗?这是我需要的:
我有一个名为 tags
的 table,它是一个存储名称和值的 table,以及拥有标签的用户 ID 和 ID 等信息标签本身。对于此问题的上下文,您只需要了解以下列:
id
: 标签本身的Id (BIGSERIAL)guild_id
: tag所在公会的id(BIGINT)。一个公会本质上就是一大群用户在一个巨大的房间里,每个tag只关联一个群。owner_id
: 拥有标签的用户id (BIGINT)。created_at
:标签创建时间的UTC时间戳(TIMESTAMP)。
我需要允许版主将公会中每个用户的所有多余标签删除到特定限制,首先优先处理较旧的标签。例如,假设这是我的 table:
id | guild_id | owner_id | created_at
----+--------------------+--------------------+----------------------------
14 | 715039810976219206 | 322896727071784960 | 2022-03-30 21:47:36.81417
17 | 715039810976219206 | 600855080962490396 | 2022-03-31 00:57:18.024558
20 | 715039810976219206 | 322896727071784960 | 2022-03-31 01:03:57.586239
21 | 715039810976219206 | 322896727071784960 | 2022-03-31 01:35:13.426953
22 | 715039810976219206 | 322896727071784960 | 2022-04-14 02:02:46.852122
25 | 715039810976219206 | 322896727071784960 | 2022-04-14 02:03:13.559069
26 | 239865610974543234 | 322896727071784960 | 2022-04-14 02:03:18.885876
当版主尝试以 3 的限制和 715039810976219206 的公会执行此功能时,它将执行以下操作:
- 对于
owner_id
列中的每个用户,它将确定他们是否在特定公会 中拥有 3 个或更多标签 。在此示例中,用户 322896727071784960 在公会 715039810976219206. 中拥有超过 3 个标签
- 然后它将继续删除所有标签,直到标签只剩下3个。 重要的是它首先优先删除旧标签。在这种情况下,它将删除标签 14 和 20。这将导致公会 715039810976219206 中的用户 322896727071784960 只剩下 3 个标签.
我已经尝试了一段时间了,如果有帮助的话,这是我到目前为止所得到的:
DELETE FROM tags
WHERE id IN (
SELECT id FROM tags
WHERE guild_id = AND owner_id = ???? ORDER BY created_at DESC
OFFSET
);
(那个????是因为我完全失去了我在做什么)
希望我已经解释清楚,让您能够理解。任何帮助将不胜感激,如果可能的话,对答案的解释将很有帮助。
如果我对你的问题的理解正确,你可以使用 rank() 函数并按 owner_id 对它们进行分组,然后按分区日期排序。然后删除所有排名高于 3 的记录。
DELETE FROM tags WHERE id in (
SELECT id FROM
(
SELECT id,
owner_id,
rank() over (partition by owner_id order by created_at desc) as rnk
FROM tags
) as t
WHERE t.rnk > 3
);
SELECT * FROM tags