简体   繁体   中英

MySQL select records, count duplicates

I have a table of posts, each post has an IP address, I want to see how many times that IP has posted by counting how many times it occurs in the database, and then putting the number of times it's appeared on the screen. Basically this:

MySQL Table:

id entry     ip
1   abc  19.123.14.5
2   cde  19.123.14.5
3   efg  12.231.22.9

I want the code to take that, count duplicates, and ouput the count like so:

id entry     ip       count
1   abc  19.123.14.5    2
2   efg  12.231.22.9    1

Here's my code (that doesn't work) so far:

  $result = mysql_query("SELECT ip, entry, id, COUNT(ip) AS A FROM table_name AS C GROUP BY ip HAVING COUNT A > 1 ORDER BY id DESC");
    $i = 0;
    while($row = mysql_fetch_array($result)) {
        $id = $row['id'];
        $entry = $row['entry'];
        $ip = $row['ip'];
        $count = ?????;
        $i++;
    ?>

    <tr width="100%" align="center">
        <td><?php echo $i; ?></td>
        <td><?php echo $id; ?></td>
        <td><?php echo $entry; ?></td>
        <td><?php echo $ip; ?></td>
        <td><?php echo $count ?></td>
        <td>
        <form style="display:inline;" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
            <input type="hidden" value="<?php echo $ip; ?>" name="ip" />
            <input type="hidden" value="<?php echo $id; ?>" name="id" />
            <input type="submit" value="Ban IP" name="submit" />
        </form>
        </td>
    </tr>

    <?php
    }

Any help would be much appreciated!

EDIT: Doesn't work: Well firstly, as obvious from my code, the variable $count has nothing assigned to it as I have no idea what to put there. Secondly, I get this error:

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource
SELECT ip, min(entry), max(id) as id, COUNT(ip) AS A 
FROM table_name AS C 
GROUP BY ip
ORDER BY max(id) DESC

You were missing to do MAX(id) since you want to group by IP and entry. You can drop the Having>1 since you want to see counts =1 according to your sample output

Sample script:

declare @table table
(
id int,
entry varchar(20),
ip varchar(20)
)
    insert into @table
    values

(1,   'abc',  '19.123.14.5'),
(2,   'cde' , '19.123.14.5'),
(3 ,  'efg',  '12.231.22.9')


SELECT  max(id) as id, ip, max(entry), COUNT(ip) AS count 
FROM @table AS C 
GROUP BY ip
ORDER BY max(id) asc

Produces:

id          ip                                        count
----------- -------------------- -------------------- -----------
2           19.123.14.5          cde                  2
3           12.231.22.9          efg                  1

You have different id s and entries for ip=19.123.14.5 . Which one of them you wish to choose?

For just counting ip s and ignoring id and entry altogether:

SELECT ip, COUNT(*)
FROM table_name
GROUP BY ip

12.231.22.9, 1
19.123.14.5, 2

For selecting a random row out of many that might be connected to the same ip (this is MySQL specific and would not work under other databases):

SELECT id, entry, ip, COUNT(*)
FROM table_name
GROUP BY ip

3, efg, 12.231.22.9, 1
1, abc, 19.123.14.5, 2 // Might also be: 2, cde, 19.123.14.5, 2

For selecting all rows, together with ip counts:

SELECT *, (SELECT COUNT(*) FROM table_name t2 WHERE t1.ip = t2.ip)
FROM
    table_name t1

1, abc, 19.123.14.5, 2
2, cde, 19.123.14.5, 2
3, efg, 12.231.22.9, 1
SELECT t.id, t.entry, t.ip, q.IpCount 
    FROM (SELECT ip, MIN(id) AS MinId, COUNT(*) AS IpCount
              FROM table_name
              GROUP BY ip) q
        INNER JOIN table_name t
            ON q.ip = t.ip
                AND q.MinId = t.id
    ORDER BY t.id DESC;

I believe that your result/example table that you want to build has something that is not that rational. You cannot combine ID and ENTRY with counter of IPs. For example, the first row in your result / example table says that IP 19.123.14.5 has been found 2 times, which is correct, but associates it to ID 1 and ENTRY abc . Why? What is the reason you do not associate it to ID 2 and ENTRY cde . There is also another mistake (? ... I cannot tell ...) on the row with ID 2 and ENTRY efg . This combination does not exist in the initial table that you give. The resulting table with all 4 columns says nothing.

Unless you want to display always the first (minimum) ID, ENTRY that the particular IP was found. Is that so?

If this is so then your SQL is not correct. The correct SQL is:

 select aa.min_id as id, 
           b.entry, 
           aa.ip as ip, 
           aa.count_ip as count     
 from table_name b     
 join (select min(a.id) as min_id, 
                 a.ip, 
                 count(a.ip) as count_ip 
          from table_name a 
          group by a.ip) aa 
      on aa.min_id = b.id;

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