每5个铜徽章获得一个银徽章

我们创建了一个铜牌徽章,用户互助,授予那些试图帮助其他用户的用户。该徽章是手动授予的(以便区分有帮助的尝试和“我也是”的回复)。

我们希望为 5 个铜牌徽章授予一个银牌徽章,无价

我编写的 SQL 找到了正确的两个用户,但每个用户只找到一次:

SELECT user_id, current_timestamp AS granted_at 
FROM user_badges
WHERE badge_id = 110 -- Users Helping Users
    AND (:backfill OR user_id IN (:user_ids))
GROUP BY user_id
HAVING COUNT(*) >= 5

我的 SQL 是否缺少了什么 :magic_wand: 魔力,还是乘法发生在 SQL 之外?

另外,我不太清楚数学是如何计算的,这样我的两个用户就不会每天都获得新徽章(这将作为夜间触发器运行),即使他们没有获得 5 个新的铜牌徽章。

是否有我搜索未找到的指南?

好的,更深入的搜索让我找到了一条线索,最终指向了指南

回填(backfill)的事情仍然有点模糊,但我已经决定(显而易见地!)在我们的测试实例上试用这个。我猜回填是在夜间运行的,所以明天我会了解更多。

除非你勾选“可以多次授予”,否则即使他们第二次(或更多次)符合条件,它也只会被授予一次。:+1:


好的,我更仔细地阅读了你的帖子,我认为我对你想要实现的目标有了更清晰的认识。

根据当前的 SQL,即使你允许它被多次授予,这些用户也只会获得一次银徽章:

  • 我已经在我的测试站点上创建了相关的徽章(包括允许多次授予)
  • 授予了 5 个铜徽章并运行了后台作业以授予徽章(银徽章已成功授予 :partying_face:
  • 然后我再次运行了 BadgeGrant 作业,但他们没有第二次获得银徽章
  • 然后我将他们的铜徽章数量增加到 11 个,并再次运行了徽章授予作业
  • 没有第二次授予银徽章

我检查了“多次”

但只授予了一次,尽管应该授予两次

1 个赞

那么……我该怎么做才能让我的用户获得他应得的 12 枚铜牌徽章和 2 枚银牌徽章?

1 个赞

这是一个好问题,我一时半会儿不知道答案。:slight_smile:

我初步想到了使用 RANK,但我可能是在徒劳地挣扎……:thinking:


粗略原型...
WITH badge_count AS (

    SELECT 
        user_id,
        granted_at,
        RANK() OVER (PARTITION BY user_id ORDER BY granted_at ASC) AS rank
    FROM user_badges
    WHERE badge_id = 110

)

SELECT user_id, granted_at
FROM badge_count
WHERE rank IN (5,10,15,20,25,30,35,40,45,50)

好的,第二次尝试使用 ROW_NUMBER

WITH badge_count AS (

    SELECT 
        user_id,
        granted_at,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY granted_at ASC) AS row
    FROM user_badges
    WHERE badge_id = 110

)

SELECT user_id, granted_at
FROM badge_count
WHERE row % 5 = 0

不过,在进一步测试后,这在预览中工作正常,但在实际的 badge grant 作业运行时并没有多次授予。我不太确定为什么。:thinking:

我把自己搞糊涂了。我要去喝杯茶,重新整理一下思路。:slight_smile:

1 个赞

嗯……昨天我又给了我的用户 4 个铜牌,看看隔夜运行是否至少能添加他刚刚“获得”的新徽章。(我想如果我不得不手动赶上其他人,我也可以。)但即使那样也没用。

我无法帮助您处理此查询,但建议您向 Discourse AI 机器人寻求帮助 - 选择顶部的机器人图标
image → GPT-4 → SQL Helper。

我发现它在根据我的需求创建数据浏览器查询方面非常出色,并且猜测它也可以帮助创建徽章查询。

1 个赞

不是每个人都有那个,Toni :shushing_face: 你会让别人嫉妒的。:slight_smile: (不过 @ganncamp 有,所以这是一个选项)

但是……我相当确定我的查询是正确的。它在预览中能正确挑选出用户,但在使用“每日更新”触发器时,它就不能授予多个徽章。

我设置了另一个几乎相同的测试,基于“在特定主题中发帖5次”的徽章,使用“当用户创建或编辑帖子”的触发器——那个测试运行完美。我正在询问它们之间有什么区别……

这是用于比较的测试徽章的 SQL,如果有人能发现任何问题的话:

WITH post_count AS (

    SELECT 
        user_id,
        id,
        created_at,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at ASC) AS row
    FROM posts
    WHERE topic_id = 864

)

SELECT user_id, created_at granted_at, id post_id
FROM post_count
WHERE row % 5 = 0
  AND (:backfill OR id IN (:post_ids))

2 个赞

我能访问它 @tpetrov,但我的尝试……收效甚微。或者也许我只是擅长问难题?:laughing:

1 个赞

经过一番探索和咨询,似乎自动徽章授予器只会授予基于特定帖子的多个徽章。所以这类徽章只会授予第一个徽章(预览具有误导性 :frowning:)。

我认为在类似情况下,“升级”徽章效果很好(例如已解决的徽章)。所以例如,银牌授予 30 个,金牌授予 100 个,如果这可能是一个可行的替代方案?

所以……即使铜牌是根据帖子授予的……那也不算,对吧?

我不知道。我不认为我理解这个问题。 :laughing:

我猜这个建议不是要找 5 个徽章,而是要找 5 个已授予徽章的帖子?我可以做到。在我“查找要授予徽章的新帖子”的报告中,我已经或多或少地完成了这项工作。

嗯。:thinking: 我觉得我明白你的意思了。让我再试试……


@ganncamp - 我认为我们可能取得了一些进展…… :slight_smile:

根据铜徽章 A 的授予方式(通过帖子扳手或在 /admin/users/{user_id}/{username}/badges 页面提供理由):

那么我认为这是完全可能的。 :partying_face:

WITH badge_count AS (

    SELECT 
        user_id,
        granted_at,
        post_id,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY granted_at DESC) AS row
    FROM user_badges
    WHERE badge_id = 110
      AND post_id IS NOT NULL
)

SELECT user_id, granted_at, post_id
FROM badge_count
WHERE row % 5 = 0
  AND (:backfill OR post_id IN (:post_ids))

(添加 AND post_id IS NOT NULL 可以防止在没有人提供理由而授予徽章时出错,否则会失败)

我刚刚试了一下,通过触发 GrantBadge 后台作业来快进,我的测试用户终于获得了他们应得的全部荣誉。 :slight_smile:

然后我为他们授予了 5 个不同的帖子的另外 5 个铜徽章 A,并再次运行: :tada:

3 个赞

感谢 @JammyDodger:tada: :tada: :tada:

我已经在我自己的测试实例上设置好了(不是我不信任你 :joy:),希望这周就能投入生产! :star_struck:

而且……是不是现在问一下,能否将你在此过程中学到的东西更新到教程中呢? :smiley:

当然。信任但验证绝对是明智的选择。 :slight_smile:

我会看看是否能添加一点东西。 :slight_smile: :+1:

2 个赞

好吧……当作业在夜间运行时,
我拥有 6 枚铜牌的用户获得了 1 枚银牌 :white_check_mark:
我拥有 13 枚铜牌的用户获得了…… 1 枚银牌 :slightly_frowning_face:

教程中的这部分让我认为不需要单独的、明确的回填作业

由于每天都会运行完整的反向填充,无论如何都必须将其考虑在内,并包含对 :backfill 参数的处理。

对于已经获得超过 1 枚银牌的用户,我该如何让他们获得奖励?我必须手动操作吗?

回填是日常工作。“每日更新”触发器基本上就是这样,而其他触发器则更像是“即时”的(例如,如果一个徽章使用“当用户创建或编辑帖子时”的触发器,则无需等到第二天晚上即可授予)。

您能弹出徽章的截图给我看看有什么不同吗?

给你:

顺便说一句,我检查其中一些东西是因为……我不知道我在做什么 :joy:

1 个赞

您的用户“Badge A”拥有 13 个徽章,当您查看他们的 /admin/users/{user_id}/{username}/badges 页面时,原因已填写?

您已将重要的部分相同。 :slight_smile: 其他部分仍然是合法的,但可选。

您是在暂存站点还是在自托管测试站点上运行此程序?

哇!谜团解开了!

我曾以为这个任务是在(我的)凌晨运行的。

事实上,我最初是随意授予该用户徽章的,所以昨天我撤销了所有徽章,挖出了他之前的帖子并重新授予。任务在我授予徽章的过程中运行。

顺便说一句,这在我的暂存站点上。

我想第二个徽章将在几小时后授予,但我希望一次授予多个徽章。如果我撤销银徽章,这种情况会发生吗?他会在……2小时后获得2个新的银徽章吗?

1 个赞