SQL子查询计数条件

时间:2014-03-06 16:37:39

标签: mysql sql

这是一个非常具体的问题。但过去几个小时我一直在墙上撞到我的头,所以我会尽力解释它。

让我说我有:

  • 用户
  • 玩过的游戏(与用户关联,有创作日期)
  • 徽章已解锁(与用户和游戏相关联,具有创建日期)

我正在寻找一个查询,列出为特定用户解锁的所有徽章以及用户在解锁徽章之前玩了多少游戏。

SELECT users.id, 
       games.id, 
       badge.id, 
       games.created game_created,
       users_badges.created AS badge_created,
       subquery.nb_games 
  FROM badges 
       INNER JOIN users_badges 
                  ON badges.id = users_badges.badge_id 
       INNER JOIN users 
                  ON users_badges.user_id = users.id 
       INNER JOIN games 
                  ON users.id = games.user_id 
       INNER JOIN ( SELECT user_id, 
                           created, 
                           COUNT(*) AS nb_games 
                      FROM games 
                    GROUP BY 
                           user_id
                    ) subquery 
                  ON subquery.user_id = users.id 
                  AND subquery.created <= users_badges.created
 WHERE users.id = 1

我的GROUP BY声明显然使我的加入条件无效,我最终总是获得所玩的游戏总数:

+----------+----------+----------+----------+---------------------+---------------------+
| users.id | games.id | badge.id | nb_games | game_created        | badge_created       |
+----------+----------+----------+----------+---------------------+---------------------+
| 1        | 1        | 1        | 3        | 2014-03-12 00:00:00 | 2014-03-12 00:00:00 |
+----------+----------+----------+----------+---------------------+---------------------+
| 1        | 2        | 2        | 3        | 2014-03-13 00:00:00 | 2014-03-13 00:00:00 |
+----------+----------+----------+----------+---------------------+---------------------+
| 1        | 3        | 3        | 3        | 2014-03-14 00:00:00 | 2014-03-14 00:00:00 |
+----------+----------+----------+----------+---------------------+---------------------+

虽然我会期待一些更为渐进的事情:

+----------+----------+----------+----------+---------------------+---------------------+
| users.id | games.id | badge.id | nb_games | game_created        | badge_created       |
+----------+----------+----------+----------+---------------------+---------------------+
| 1        | 1        | 1        | 1        | 2014-03-12 00:00:00 | 2014-03-12 00:00:00 |
+----------+----------+----------+----------+---------------------+---------------------+
| 1        | 2        | 2        | 2        | 2014-03-13 00:00:00 | 2014-03-13 00:00:00 |
+----------+----------+----------+----------+---------------------+---------------------+
| 1        | 3        | 3        | 3        | 2014-03-14 00:00:00 | 2014-03-14 00:00:00 |
+----------+----------+----------+----------+---------------------+---------------------+

这可能吗?

1 个答案:

答案 0 :(得分:1)

这可以在没有子查询的情况下实现。在您的情况下,您首先计算每个用户的游戏数量(因此是计算每个用户的总数),在此之后,您将尝试检查游戏日期。

此外,我发现一个问题,即您已经连接了两次游戏,如果您需要用户 - 徽章 - 之前的游戏则不需要。它只需要一次

以下是如何解决问题

SELECT users.id, 
   game.id, 
   badge.id, 
   users_badges.created AS badge_created,
   COUNT(gamesBefore.id)_games 
FROM badges 
   INNER JOIN users_badges 
              ON badges.id = users_badges.badge_id 
   INNER JOIN users 
              ON users_badges.user_id = users.id 
   INNER JOIN games AS gamesBefore
              ON users.id = game.user_id 
              AND gamesBefore.created <= users_badges.created
WHERE users.id = 1
GROUP BY user.id, badge.id

所以稍微解释一下 - 你需要为用户X徽章选择所有可能的计数 - 所以我们按他们的ID分组并计算之前的游戏数量。正如我之前提到的那样 - 根据你的要求,你不需要两次加入游戏。