0

我正在使用 MySQL

我有三张桌子:

accounts {
    account_id,
    username
}

account_ips {
    idaccount_ips,
    account_id,
    ip
}

account_bans {
    ban_id
    account_id,
    expires
}

需要获取不在禁令表中的每个 ip 的帐户分组计数。(见下方查询)

我尝试了以下方法,但速度太慢(44s):

SELECT DISTINCT a.account_id, count(DISTINCT a.account_id)
  FROM account_ips AS a
 WHERE NOT EXISTS(
    SELECT 1
      FROM account_bans AS b
     WHERE b.expires > 1340341272 AND b.account_id = a.account_id)
 GROUP BY a.ip
HAVING count(DISTINCT a.account_id) > 3
 ORDER BY count(DISTINCT a.account_id) DESC;

解释输出以下内容:

1, 'PRIMARY', 'a', 'ALL', '', '', '', '', 304745, 'Using where; Using temporary; Using filesort'
2, 'DEPENDENT SUBQUERY', 'b', 'ALL', '', '', '', '', 1851, 'Using where'
4

2 回答 2

2

你需要这样做 -

SELECT AIP.IP, COUNT(AIP.ACCOUNT_ID)
FROM ACCOUNT_IPS AIP
LEFT JOIN ACCOUNTS A ON AIP.ACCOUNT_ID=A.ACCOUNT_ID
LEFT JOIN ACCOUNT_BANS AB ON A.ACCOUNT_ID=AB.ACCOUNT_ID
WHERE
AB.BAN_ID IS NULL
GROUP BY AIP.IP

如果您还需要考虑 b.expires > 1340341272 那么查询将是 -

SELECT AIP.IP, COUNT(AIP.ACCOUNT_ID)
FROM ACCOUNT_IPS AIP
LEFT JOIN ACCOUNTS A ON AIP.ACCOUNT_ID=A.ACCOUNT_ID
LEFT JOIN ACCOUNT_BANS AB ON A.ACCOUNT_ID=AB.ACCOUNT_ID
WHERE
AB.BAN_ID IS NULL
OR AB.EXPIRES <= 1340341272
GROUP BY AIP.IP
于 2012-06-22T05:05:56.907 回答
0

尝试 aleft join并在右表中获取 ips 的空值,而不是WHERE NOT EXISTS.

FROM account_ips a
LEFT JOIN account_bans b ON b.account_id = a.account_id
WHERE b.account_id IS NULL 
于 2012-06-22T05:06:46.480 回答