SQL订单和分组依据

时间:2012-12-06 11:24:44

标签: sql

我在查询中执行某些查找时有点迷失。 我有查询的第一部分,它返回了我在帐户中遗漏了一些条目的所有帐户。现在我需要根据上次登录尝试进一步过滤此子集。

表格结构如下:

  • users表包含所有用户信息。我们只关心project_id 33下的用户。
  • users_account_list包含用户拥有的所有帐户。我们只关心没有服务条目的用户50。
  • users_login_logs包含用户的所有登录尝试。

原始查询我有这个:

SELECT u.id,
       u.login, 
       u.email, 
       u.nickname,
       b.station_login AS "additionals.station_login",
       a.id AS "user_account_list.id",
       a.game_id AS "user_account_list.game_id",
       a.game_uid AS "user_account_list.game_uid",
       c.created_at AS "last login"
FROM users u
LEFT JOIN user_account_list a ON u.id = a.user_id AND a.game_id = 50
LEFT JOIN user_additionals b ON u.id = b.id
LEFT JOIN user_login_logs c ON u.id = c.user_id
WHERE u.project_id = 33
AND u.verified_at IS NOT NULL
AND (a.id IS NULL OR a.game_id IS NULL OR a.game_uid IS NULL)
AND (b.station_login IS NULL OR b.station_login = '')
ORDER BY c.created_at DESC

这将返回已在project_id 33下注册的所有用户,并且没有game_id 50的条目,并且没有信息存储在其附加信息表中。可选,但不相关,只是限制返回的数据。它确实给了我每个用户多行,根据他们的最新登录日期排序。

我需要的是每个用户返回最多只有一行的最新登录日期。 我尝试用u.id 替换ORDER BY,但是这给了我最早的结果,而不是最新的结果。

我怎么能:

  • 将返回的行数限制为每个用户只有一行
  • 确保该行基于用户的最新登录尝试。

修改

这是查询当前返回的内容:

+----+-------+-----------------+----------+---------------------------+----------------------+---------------------------+----------------------------+---------------------+
| id | login | email           | nickname | additionals.station_login | user_account_list.id | user_account_list.game_id | user_account_list.game_uid | last login          |
+----+-------+-----------------+----------+---------------------------+----------------------+---------------------------+----------------------------+---------------------+
|  1 | usrnm | someon@mail.com | Nickname |                           |                 NULL |                      NULL | NULL                       | 2012-10-19 00:00:00 |
|  1 | usrnm | someon@mail.com | Nickname |                           |                 NULL |                      NULL | NULL                       | 2012-10-18 00:00:00 |
|  1 | usrnm | someon@mail.com | Nickname |                           |                 NULL |                      NULL | NULL                       | 2012-10-17 00:00:00 |
+----+-------+-----------------+----------+---------------------------+----------------------+---------------------------+----------------------------+---------------------+
3 rows in set (0.08 sec)

2 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是JOINuser_login_logs,使用下表:

   SELECT user_id, MAX(created_at) LatestDate
   FROM user_login_logs 
   GROUP BY user_id

并加入created_at = LatestDate。这会将用户登录日志限制为每个用户的最新创建日期。这是您的查询:

SELECT u.id,
       u.login, 
       u.email, 
       u.nickname,
       b.station_login AS "additionals.station_login",
       a.id AS "user_account_list.id",
       a.game_id AS "user_account_list.game_id",
       a.game_uid AS "user_account_list.game_uid",
       c.created_at AS "last login"
FROM users u
LEFT JOIN user_account_list a ON u.id = a.user_id AND a.game_id = 50
LEFT JOIN user_additionals b ON u.id = b.id
LEFT JOIN user_login_logs c ON u.id = c.user_id
LEFT JOIN
(
   SELECT user_id, MAX(created_at) LatestDate
   FROM user_login_logs 
   GROUP BY user_id
) maxc ON c.userid = maxc.userid AND c.created_at = maxc.LatestDate
WHERE u.project_id = 33
AND u.verified_at IS NOT NULL
AND (a.id IS NULL OR a.game_id IS NULL OR a.game_uid IS NULL)
AND (b.station_login IS NULL OR b.station_login = '')
ORDER BY c.created_at DESC;

请注意:您是LEFT JOIN表,因此左连接表中不匹配的行将包含在结果集中。如果您不需要将它们包含在结果集中,请改用INNER JOIN

答案 1 :(得分:2)

您需要在尝试时将ORDER BY替换为GROUP by u.id,但您还需要在SELECT中指明您希望群组中的最后一个日期,以便您需要替换

c.created_at AS "last login"

通过

MAX(c.created_at) AS "last login"

由于GROUP BY,每个用户只返回一行,并且您只会为MAX()

选择每个用户的最新日期

编辑:我认为你应该避免使用带有空格的别名列名来避免错误