Mysql – SQL Limit + count group

countlimitsMySQLorder-by

I'm tracking all the visitors of my site using this table:

Visitors table

In my admin panel, I have an overview of which countries visited my site, where they came from, …, but because over 20+ different countries have visited my site already, the chart looks like this:

Messed up chart

To solve this, I want to select the top 5 countries, but I have no clue on how to do this.

I've tried using LIMIT & COUNT but no luck.

Best Answer

You can separate the problem into multiple steps.

First lets create an example table:

SQL Fiddle

MySQL 5.5.32 Schema Setup:

CREATE TABLE Visitors(
  id INT,
  -- other columns
  country CHAR(2)
);

INSERT INTO Visitors(id,country)VALUES(1,'DE');
INSERT INTO Visitors(id,country)VALUES(2,'DE');
INSERT INTO Visitors(id,country)VALUES(3,'DE');
INSERT INTO Visitors(id,country)VALUES(4,'BE');
INSERT INTO Visitors(id,country)VALUES(5,'BE');
INSERT INTO Visitors(id,country)VALUES(6,'BE');
INSERT INTO Visitors(id,country)VALUES(7,'BE');
INSERT INTO Visitors(id,country)VALUES(8,'BE');
INSERT INTO Visitors(id,country)VALUES(9,'BE');
INSERT INTO Visitors(id,country)VALUES(10,'US');
INSERT INTO Visitors(id,country)VALUES(11,'US');
INSERT INTO Visitors(id,country)VALUES(12,'US');
INSERT INTO Visitors(id,country)VALUES(13,'US');
INSERT INTO Visitors(id,country)VALUES(14,'HR');
INSERT INTO Visitors(id,country)VALUES(15,'HR');
INSERT INTO Visitors(id,country)VALUES(16,'SE');
INSERT INTO Visitors(id,country)VALUES(17,'SE');
INSERT INTO Visitors(id,country)VALUES(18,'SE');
INSERT INTO Visitors(id,country)VALUES(19,'SE');
INSERT INTO Visitors(id,country)VALUES(20,'RU');

The first step now is to count the impressions per country using the GROUP BY clause:

Query 1:

SELECT country,COUNT(1) cnt
FROM Visitors
GROUP BY country

Results:

| COUNTRY | CNT |
-----------------
|      BE |   6 |
|      DE |   3 |
|      HR |   2 |
|      RU |   1 |
|      SE |   4 |
|      US |   4 |

From there we can get the top 5 countries using LIMIT:

Query 2:

SELECT *
FROM(
  SELECT country,COUNT(1) cnt
  FROM Visitors
  GROUP BY country
)V
ORDER BY cnt DESC
LIMIT 5

Results:

| COUNTRY | CNT |
-----------------
|      BE |   6 |
|      SE |   4 |
|      US |   4 |
|      DE |   3 |
|      HR |   2 |

Now we just need to join the result back to the visitors table:

Query 3:

SELECT V.*,c.cnt 
FROM Visitors V
JOIN(
  SELECT *  
  FROM(
    SELECT country,COUNT(1) cnt
    FROM Visitors
    GROUP BY country
  )V
  ORDER BY cnt DESC
  LIMIT 5
)C
ON V.country = C.country

Results:

| ID | COUNTRY | CNT |
----------------------
|  1 |      DE |   3 |
|  2 |      DE |   3 |
|  3 |      DE |   3 |
|  4 |      BE |   6 |
|  5 |      BE |   6 |
|  6 |      BE |   6 |
|  7 |      BE |   6 |
|  8 |      BE |   6 |
|  9 |      BE |   6 |
| 10 |      US |   4 |
| 11 |      US |   4 |
| 12 |      US |   4 |
| 13 |      US |   4 |
| 14 |      HR |   2 |
| 15 |      HR |   2 |
| 16 |      SE |   4 |
| 17 |      SE |   4 |
| 18 |      SE |   4 |
| 19 |      SE |   4 |
Related Question