我有一个访问者列表,其中记录了我的IP。现在,我需要查看每位访客来自哪个国家/地区。
我将此任务分为两部分,首先获取具有唯一登录用户的所有IP,第二部分是搜索具有国家/ IP信息的两个表(来自ip2nation)并获取提供的国家/地区IP
SELECT
a.uid, a.hostname, a.timestamp,
COUNT(*) AS times
FROM
login_activity a
GROUP BY
a.hostname
ORDER BY
times desc
这给了我所有过去登录用户的IP(主机名)。工作正常。
SELECT
c.country
FROM
ip2nationCountries c, ip2nation i
WHERE
i.ip < INET_ATON( "157.191.122.36" )
AND
c.code = i.country
ORDER BY i.ip DESC
LIMIT 0 , 1
这也很有用。
现在,对于真正的问题。加入这两个查询,从所有登录用户获取国家(而不是IP)。这就是我写的: -
SELECT
a.uid, a.hostname, a.timestamp, c.country,
COUNT(*) AS times
FROM
login_activity a, ip2nationCountries c, ip2nation i
WHERE
i.ip < INET_ATON(a.hostname)
AND c.code = i.country
GROUP BY
a.hostname
ORDER BY
times desc;
这有两个问题: -
你能帮我制作这个SQL吗?
以防万一,表格的结构/数据如下: -
(结构)
CREATE TABLE ip2nation (
ip int(11) unsigned NOT NULL default '0',
country char(2) NOT NULL default '',
KEY ip (ip)
);
(数据)
INSERT INTO ip2nation (ip, country) VALUES(0, 'us');
INSERT INTO ip2nation (ip, country) VALUES(687865856, 'za');
INSERT INTO ip2nation (ip, country) VALUES(689963008, 'eg');
INSERT INTO ip2nation (ip, country) VALUES(691011584, 'za');
INSERT INTO ip2nation (ip, country) VALUES(691617792, 'zw');
INSERT INTO ip2nation (ip, country) VALUES(691621888, 'lr');
INSERT INTO ip2nation (ip, country) VALUES(691625984, 'ke');
INSERT INTO ip2nation (ip, country) VALUES(691630080, 'za');
INSERT INTO ip2nation (ip, country) VALUES(691631104, 'gh');
INSERT INTO ip2nation (ip, country) VALUES(691632128, 'ng');
INSERT INTO ip2nation (ip, country) VALUES(691633152, 'zw');
INSERT INTO ip2nation (ip, country) VALUES(691634176, 'za');
INSERT INTO ip2nation (ip, country) VALUES(691650560, 'gh');
INSERT INTO ip2nation (ip, country) VALUES(691666944, 'ng');
INSERT INTO ip2nation (ip, country) VALUES(691732480, 'tz');
INSERT INTO ip2nation (ip, country) VALUES(691798016, 'zm');
INSERT INTO ip2nation (ip, country) VALUES(691863552, 'za');
INSERT INTO ip2nation (ip, country) VALUES(691994624, 'zm');
INSERT INTO ip2nation (ip, country) VALUES(692011008, 'za');
INSERT INTO ip2nation (ip, country) VALUES(692027392, 'mg');
INSERT INTO ip2nation (ip, country) VALUES(692035584, 'ao');
INSERT INTO ip2nation (ip, country) VALUES(692043776, 'na');
INSERT INTO ip2nation (ip, country) VALUES(692060160, 'eg');
INSERT INTO ip2nation (ip, country) VALUES(692191232, 'ci');
INSERT INTO ip2nation (ip, country) VALUES(692207616, 'za');
INSERT INTO ip2nation (ip, country) VALUES(692240384, 'gh');
INSERT INTO ip2nation (ip, country) VALUES(692256768, 'sd');
(结构)
CREATE TABLE ip2nationCountries (
code varchar(4) NOT NULL default '',
iso_code_2 varchar(2) NOT NULL default '',
iso_code_3 varchar(3) default '',
iso_country varchar(255) NOT NULL default '',
country varchar(255) NOT NULL default '',
lat float NOT NULL default '0',
lon float NOT NULL default '0',
PRIMARY KEY (code),
KEY code (code)
);
(数据)
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('ad', 'AN', 'AND', 'Andorra', 'Andorra', 42.3, 1.3);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('ae', 'AR', 'ARE', 'United Arab Emirates', 'United Arab Emirates', 24, 54);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('af', 'AF', 'AFG', 'Afghanistan', 'Afghanistan', 33, 65);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('ag', 'AT', 'ATG', 'Antigua and Barbuda', 'Antigua and Barbuda', 17.03, -61.48);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('ai', 'AI', 'AIA', 'Anguilla', 'Anguilla', 18.15, -63.1);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('al', 'AL', 'ALB', 'Albania', 'Albania', 41, 20);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('am', 'AR', 'ARM', 'Armenia', 'Armenia', 40, 45);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('an', 'AN', 'ANT', 'Netherlands Antilles', 'Netherlands Antilles', 12.15, -68.45);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('ao', 'AG', 'AGO', 'Angola', 'Angola', -12.3, 18.3);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('aq', 'AT', 'ATA', 'Antarctica', 'Antarctica', -90, 0);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('ar', 'AR', 'ARG', 'Argentina', 'Argentina', -34, -64);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('as', 'AS', 'ASM', 'American Samoa', 'American Samoa', -14.2, -170);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('at', 'AU', 'AUT', 'Austria', 'Austria', 47.2, 13.2);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('au', 'AU', 'AUS', 'Australia', 'Australia', -27, 133);
INSERT INTO ip2nationCountries (code, iso_code_2, iso_code_3, iso_country, country, lat, lon) VALUES('aw', 'AB', 'ABW', 'Aruba', 'Aruba', 12.3, -69.58);
(结构)
CREATE TABLE IF NOT EXISTS `mslop_login_activity` (
`aid` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'The primary identifier for an activity (session).',
`uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'The mslop_users.uid corresponding to a session, or 0 for anonymous user.',
`host_user_agent` varchar(256) NOT NULL DEFAULT '' COMMENT '$_SERVER["HOST_USER_AGENT"] string. This can be used with get_browser() in PHP.',
`hostname` varchar(128) NOT NULL DEFAULT '' COMMENT 'The IP address that was used for this session.',
`timestamp` int(11) NOT NULL DEFAULT '0' COMMENT 'The UNIX timestamp when the session was started.',
PRIMARY KEY (`aid`),
KEY `aid` (`aid`),
KEY `uid` (`uid`),
KEY `timestamp` (`timestamp`)
);
(数据)
INSERT INTO `mslop_login_activity` (`aid`, `uid`, `host_user_agent`, `hostname`, `timestamp`) VALUES
(1, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0', '172.24.1.143', 1363038356),
(2, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0', '172.24.1.143', 1363038374),
(3, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363193841),
(4, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363194789),
(5, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363197889),
(6, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17', '172.24.1.143', 1363207361),
(7, 35, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0', '172.24.1.143', 1363301612),
(8, 35, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0', '172.24.1.143', 1363301751),
(9, 1, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0', '172.24.1.143', 1363364574),
(10, 1, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363374517),
(11, 1, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363377701),
(12, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363714792),
(13, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363714911),
(14, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.57 Safari/537.17', '172.24.1.143', 1363714929),
(15, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0', '172.24.1.143', 1363715946),
(16, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.28.10 (KHTML, like Gecko) Version/6.0.3 Safari/536.28.10', '172.24.1.161', 1363791080),
(17, 4, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.28.10 (KHTML, like Gecko) Version/6.0.3 Safari/536.28.10', '172.24.1.161', 1363791124),
(18, 1, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.28.10 (KHTML, like Gecko) Version/6.0.3 Safari/536.28.10', '172.24.1.161', 1363791144),
(19, 3, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22', '172.24.1.143', 1363791365),
(20, 64, 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22', '172.24.1.143', 1363791650);
我按如下方式更改了查询,但仍然显示错误的结果......
你们可以看一下: -
SELECT l.uid,
l.hostname,
l.timestamp,
c.country,
l.times
FROM ip2nationCountries c
JOIN ip2nation i ON c.code = i.country
JOIN ( SELECT
a.uid,
a.hostname,
MAX(a.timestamp) AS timestamp,
COUNT(*) AS times
FROM mslop_login_activity a
WHERE a.uid = 3
AND a.hostname = "157.191.122.36"
GROUP BY a.hostname) AS l ON i.ip < INET_ATON( l.hostname )
答案 0 :(得分:0)
您错过了加入。如果您使用正确的连接语法,这将更加明显,因此请将此作为课程,并在将来始终使用join
和on
子句。
您想要的查询:
SELECT a.uid, a.hostname, a.timestamp, c.country, COUNT(*) AS times
FROM login_activity a left outer join
ip2nationCountries c
on a.hostname = c.ip left outer join
ip2nation i
on i.ip < INET_ATON(a.hostname) AND c.code = i.country
GROUP BY a.hostname
ORDER BY times desc;
两条评论。我做了这些left outer join
。如果主机名不匹配,则它们仍将显示在输出中(如果要过滤掉这些主机名,请更改为inner join
)。其次,在加入其他表之前,您可能希望预先聚合login_activity
表,如果它真的很大。
答案 1 :(得分:0)
这将为您提供用户ID,主机名以及他们在该主机上登录的次数。
SELECT a.uid, a.hostname, COUNT(*) AS times
FROM mslop_login_activity a
GROUP BY a.uid, a.hostname
ORDER BY times desc
要简化国家/地区,请使用视图计算范围。 (这种观点非常依赖于您获得有关IP地址如何映射到各国的准确完整数据。我没有尝试验证您的数据。)
create view ip_range as
select t1.ip as ip_start
, (select min(ip) - 1 from ip2nation where ip > t1.ip) ip_end
, t1.country
from ip2nation t1
现在你应该可以使用简单明了的联接来获得这个国家。
SELECT a.uid
, a.hostname
, inet_aton(a.hostname) as ip_int
, ip_range.country
FROM mslop_login_activity a
inner join ip_range
on inet_aton(a.hostname) between ip_range.ip_start and ip_range.ip_end
使用您的示例数据,这将不返回任何行。首先,登录活动的所有IP地址都在reserved range。另一方面,“ip2nation”中最长的IP地址(整数)是9位数;这还不够。我自己的IP地址转换为10位整数。
如果我将登录活动中的某个IP地址更新为转换为9位整数的美国IP地址,则上述查询会将该国家/地区正确识别为“US”。
这是您原始查询之一。它没有像你认为的那样做。
SELECT
a.uid, a.hostname, a.timestamp,
COUNT(*) AS times
FROM
login_activity a
GROUP BY
a.hostname
ORDER BY
times desc
返回此行。
uid hostname timestamp times
--
3 172.24.1.143 1363038356 20
但是这个查询返回12行。请注意,12行不等于20次。
SELECT uid
FROM mslop_login_activity
where uid = 3
在MySQL中使用GROUP BY是危险的,除非你知道自己在做什么,而且你真的非常小心。 (我不认为任何其他dbms将运行您的原始第一个查询,因为它不符合SQL。)