2012-12-06 69 views
0

我在查询执行特定查询时遇到了一些问题。 我有查询的第一部分,它会返回在其帐户中缺少一些条目的所有帐户。现在我需要根据他们上次的登录尝试进一步过滤这个子集。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项,并存储在任何信息的所有用户他们的附加信息表。可选但不相关,只限制返回的数据。它确实为每个用户提供了多行返回,根据它们的最新登录日期排序。

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

如何我:

  • 限行每用户
  • 返回到只有1行确保该行是基于用户的最新的登录尝试。

编辑

这是查询当前返回:

+----+-------+-----------------+----------+---------------------------+----------------------+---------------------------+----------------------------+---------------------+ 
| 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 | [email protected] | Nickname |       |     NULL |      NULL | NULL      | 2012-10-19 00:00:00 | 
| 1 | usrnm | [email protected] | Nickname |       |     NULL |      NULL | NULL      | 2012-10-18 00:00:00 | 
| 1 | usrnm | [email protected] | Nickname |       |     NULL |      NULL | NULL      | 2012-10-17 00:00:00 | 
+----+-------+-----------------+----------+---------------------------+----------------------+---------------------------+----------------------------+---------------------+ 
3 rows in set (0.08 sec) 
+0

什么是RDBMS? –

+0

mysql数据库。 –

回答

2

您需要更换ORDER BYGROUP by u.id你尝试过,但你也需要在你的SELECT指示您希望组中的最后日期,因此您需要替换

c.created_at AS "last login" 

通过

MAX(c.created_at) AS "last login" 

这将返回每个用户由于只有一行到GROUP BY,你将只选择每个用户感谢最新日期MAX()

编辑:我想你应该避免使用别名列里面的空间名称,以避免错误

做到这一点
+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

+0

这让我更接近,但下面的回复似乎返回了我想要的。不过谢谢你的好解释。 –

+0

@NekoNova - 不客气,很高兴你找到你想要的东西。 –