Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Top 'n' Ergebnisse für jedes Keyword

Da Sie das Schema für results nicht angegeben haben , ich nehme an, es ist so oder sehr ähnlich (vielleicht zusätzliche Spalten):

create table results (
  id int primary key,
  user int,
    foreign key (user) references <some_other_table>(id),
  keyword varchar(<30>)
);

Schritt 1: aggregiert nach keyword/user wie in Ihrer Beispielabfrage, aber für alle Keywords:

create view user_keyword as (
  select
    keyword,
    user,
    count(*) as magnitude
  from results
  group by keyword, user
);

Schritt 2: Jeden Benutzer innerhalb jeder Schlüsselwortgruppe einordnen (beachten Sie die Verwendung der Unterabfrage zum Einordnen der Zeilen):

create view keyword_user_ranked as (
  select 
    keyword,
    user,
    magnitude,
    (select count(*) 
     from user_keyword 
     where l.keyword = keyword and magnitude >= l.magnitude
    ) as rank
  from
    user_keyword l
);

Schritt 3: Wählen Sie nur die Zeilen aus, in denen der Rang kleiner als eine Zahl ist:

select * 
from keyword_user_ranked 
where rank <= 3;

Beispiel:

Verwendete Basisdaten:

mysql> select * from results;
+----+------+---------+
| id | user | keyword |
+----+------+---------+
|  1 |    1 | mysql   |
|  2 |    1 | mysql   |
|  3 |    2 | mysql   |
|  4 |    1 | query   |
|  5 |    2 | query   |
|  6 |    2 | query   |
|  7 |    2 | query   |
|  8 |    1 | table   |
|  9 |    2 | table   |
| 10 |    1 | table   |
| 11 |    3 | table   |
| 12 |    3 | mysql   |
| 13 |    3 | query   |
| 14 |    2 | mysql   |
| 15 |    1 | mysql   |
| 16 |    1 | mysql   |
| 17 |    3 | query   |
| 18 |    4 | mysql   |
| 19 |    4 | mysql   |
| 20 |    5 | mysql   |
+----+------+---------+

Gruppiert nach Schlüsselwort und Benutzer:

mysql> select * from user_keyword order by keyword, magnitude desc;
+---------+------+-----------+
| keyword | user | magnitude |
+---------+------+-----------+
| mysql   |    1 |         4 |
| mysql   |    2 |         2 |
| mysql   |    4 |         2 |
| mysql   |    3 |         1 |
| mysql   |    5 |         1 |
| query   |    2 |         3 |
| query   |    3 |         2 |
| query   |    1 |         1 |
| table   |    1 |         2 |
| table   |    2 |         1 |
| table   |    3 |         1 |
+---------+------+-----------+

Benutzer, die innerhalb von Schlüsselwörtern eingestuft wurden:

mysql> select * from keyword_user_ranked order by keyword, rank asc;
+---------+------+-----------+------+
| keyword | user | magnitude | rank |
+---------+------+-----------+------+
| mysql   |    1 |         4 |    1 |
| mysql   |    2 |         2 |    3 |
| mysql   |    4 |         2 |    3 |
| mysql   |    3 |         1 |    5 |
| mysql   |    5 |         1 |    5 |
| query   |    2 |         3 |    1 |
| query   |    3 |         2 |    2 |
| query   |    1 |         1 |    3 |
| table   |    1 |         2 |    1 |
| table   |    3 |         1 |    3 |
| table   |    2 |         1 |    3 |
+---------+------+-----------+------+

Nur Top 2 von jedem Schlüsselwort:

mysql> select * from keyword_user_ranked where rank <= 2 order by keyword, rank asc;
+---------+------+-----------+------+
| keyword | user | magnitude | rank |
+---------+------+-----------+------+
| mysql   |    1 |         4 |    1 |
| query   |    2 |         3 |    1 |
| query   |    3 |         2 |    2 |
| table   |    1 |         2 |    1 |
+---------+------+-----------+------+

Beachten Sie, dass bei Gleichstand – siehe Benutzer 2 und 4 für das Schlüsselwort „mysql“ in den Beispielen – alle Parteien im Gleichstand den „letzten“ Rang erhalten, d.

Leistung:Das Hinzufügen eines Index zu den Schlüsselwort- und Benutzerspalten ist hilfreich. Ich habe eine Tabelle, die auf ähnliche Weise mit 4000 und 1300 unterschiedlichen Werten für die beiden Spalten (in einer Tabelle mit 600000 Zeilen) abgefragt wird. Sie können den Index wie folgt hinzufügen:

alter table results add index keyword_user (keyword, user);

In meinem Fall sank die Abfragezeit von etwa 6 Sekunden auf etwa 2 Sekunden.