简体   繁体   中英

MySQL select all distinct values from column a for each distinct column b, where count distinct a >1

I have one table that I'm using to store all access requests for a radius server, that looks like this:

describe radius.loginattempts;
+------------------+------------------+------+-----+---------+----------------+
| Field            | Type             | Null | Key | Default | Extra          |
+------------------+------------------+------+-----+---------+----------------+
| loginattempt_key | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| log_date         | int(10) unsigned | NO   |     | NULL    |                |
| result           | tinyint(1)       | YES  |     | NULL    |                |
| username         | text             | YES  |     | NULL    |                |
| mac              | text             | YES  |     | NULL    |                |
+------------------+------------------+------+-----+---------+----------------+

Every time someone tries to log in, whether it works or not, a log entry gets created in this table.

What I want to do is get a list of all the devices that have had two or more users try to log in, and all the distinct usernames for each.

So, if I have some data that looks like this:

select * from loginattempts limit 8;
+------------------+------------+--------+----------+-------------------+
| loginattempt_key | log_date   | result | username | mac               |
+------------------+------------+--------+----------+-------------------+
|                1 | 1337035334 |      1 | kclark   | 11:11:11:11:11:11 |
|                2 | 1337035620 |      1 | kclark   | 22:22:22:22:22:22 |
|                3 | 1337035681 |      0 | guest    | 33:33:33:33:33:33 |
|                4 | 1337035740 |      1 | guest    | 22:22:22:22:22:22 |
|                5 | 1337037782 |      1 | rfogarty | 44:44:44:44:44:44 |
|                6 | 1337037789 |      1 | jsmith   | 44:44:44:44:44:44 |
|                7 | 1337037790 |      1 | jsmith   | 44:44:44:44:44:44 |
|                8 | 1337037791 |      1 | jsmith   | 44:44:44:44:44:44 |
+------------------+------------+--------+----------+-------------------+

I want one magic query that returns something like this:

+-------------------+----------+
| mac               | username |
+-------------------+----------+
| 22:22:22:22:22:22 | kclark   |
| 22:22:22:22:22:22 | guest    |
| 44:44:44:44:44:44 | rfogarty |
| 44:44:44:44:44:44 | jsmith   |
+-------------------+----------+

This will eventually be in PHP, and I can easily do it with two queries and a for loop, but as a thought experiment I've been trying to think of how to do it with a single query and some fancy joins (or even subqueries) but just can't wrap my head around it...

mysql -V
mysql  Ver 14.14 Distrib 5.1.52, for unknown-linux-gnu (x86_64) using readline 5.1

OK, I think you mean this... http://sqlfiddle.com/#!3/b6100/6

Given

create table loginattempts  
(
  login_key int,
  mac varchar(12) null,
  username varchar(12) null
)

insert into loginattempts values (1, 111, 'peter')
insert into loginattempts values (2, 111, 'bob')
insert into loginattempts values (3, 222, 'geoff')
insert into loginattempts values (4, 222, 'lisa')
insert into loginattempts values (1, 333, 'peter')

You need this query

   select mac, username
   from loginattempts
   where
    mac in
    (
      select mac
      from loginattempts
      group by mac
      having count(*) > 1
     )

Gives you

MAC USERNAME
111 peter
111 bob
222 geoff
222 lisa

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM