चूँकि आपने results
. के लिए स्कीमा नहीं दिया है , मुझे लगता है कि यह यह या बहुत समान है (शायद अतिरिक्त कॉलम):
create table results (
id int primary key,
user int,
foreign key (user) references <some_other_table>(id),
keyword varchar(<30>)
);
चरण 1: keyword/user
. द्वारा समेकित जैसा कि आपकी उदाहरण क्वेरी में है, लेकिन सभी कीवर्ड के लिए:
create view user_keyword as (
select
keyword,
user,
count(*) as magnitude
from results
group by keyword, user
);
चरण 2: प्रत्येक उपयोगकर्ता को प्रत्येक कीवर्ड समूह के भीतर रैंक करें (पंक्तियों को रैंक करने के लिए सबक्वेरी के उपयोग पर ध्यान दें):
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
);
चरण 3: केवल उन पंक्तियों का चयन करें जहाँ रैंक किसी संख्या से कम हो:
select *
from keyword_user_ranked
where rank <= 3;
उदाहरण:
उपयोग किया गया आधार डेटा:
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 |
+----+------+---------+
कीवर्ड और उपयोगकर्ता द्वारा समूहीकृत:
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 |
+---------+------+-----------+
उपयोगकर्ता कीवर्ड के भीतर रैंक करते हैं:
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 |
+---------+------+-----------+------+
प्रत्येक कीवर्ड से केवल शीर्ष 2:
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 |
+---------+------+-----------+------+
ध्यान दें कि जब संबंध होते हैं - उदाहरणों में "mysql" कीवर्ड के लिए उपयोगकर्ता 2 और 4 देखें - टाई में सभी पार्टियों को "अंतिम" रैंक मिलती है, अर्थात यदि दूसरा और तीसरा बंधा हुआ है, तो दोनों को रैंक 3 सौंपा गया है।
प्रदर्शन:कीवर्ड और उपयोगकर्ता कॉलम में एक इंडेक्स जोड़ने से मदद मिलेगी। मेरे पास दो कॉलम (600000-पंक्ति तालिका में) के लिए 4000 और 1300 अलग-अलग मानों के साथ एक समान तरीके से पूछताछ की जा रही है। आप इंडेक्स को इस तरह जोड़ सकते हैं:
alter table results add index keyword_user (keyword, user);
मेरे मामले में, क्वेरी का समय लगभग 6 सेकंड से घटकर लगभग 2 सेकंड हो गया है।