sql >> Databasteknik >  >> RDS >> Mysql

Topp 'n' resultat för varje sökord

Eftersom du inte har angett schemat för results , jag antar att det är denna eller mycket liknande (kanske extra kolumner):

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

Steg 1: samla efter keyword/user som i din exempelfråga, men för alla sökord:

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

Steg 2: rangordna varje användare inom varje sökordsgrupp (observera användningen av underfrågan för att rangordna raderna):

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
);

Steg 3: välj bara de rader där rangordningen är mindre än ett antal:

select * 
from keyword_user_ranked 
where rank <= 3;

Exempel:

Basdata som används:

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   |
+----+------+---------+

Grupperad efter nyckelord och användare:

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 |
+---------+------+-----------+

Användare rankade inom sökord:

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 |
+---------+------+-----------+------+

Endast topp 2 från varje sökord:

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 |
+---------+------+-----------+------+

Observera att när det är oavgjort -- se användare 2 och 4 för nyckelord "mysql" i exemplen -- får alla parter i oavgjort den "sista" rankningen, dvs om 2:an och 3:an är oavgjort, tilldelas båda rank 3.

Prestanda:att lägga till ett index till nyckelordet och användarkolumnerna hjälper. Jag har en tabell som efterfrågas på ett liknande sätt med 4000 och 1300 distinkta värden för de två kolumnerna (i en tabell med 600000 rader). Du kan lägga till indexet så här:

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

I mitt fall sjönk frågetiden från cirka 6 sekunder till cirka 2 sekunder.



  1. SQL design för undersökning med svar av olika datatyper

  2. PHP:Visa ja/nej bekräftelsedialog

  3. Databas + Windows-autentisering + Användarnamn/Lösenord?

  4. ODBC-fråga på MS SQL Server returnerar endast de första 255 tecknen i PHP PDO (FreeTDS)