2010-10-14 54 views
2

我有一個「產品」表。我也有一個用戶標記的關鍵字的產品表。我想根據有多少產品爲每個產品帶回頂部關鍵字。MySQL:加入關鍵字表,但只帶回最流行的

關鍵字表基本上由關鍵字,主鍵和將其鏈接到Products表的外鍵組成。

我認爲我必須加入關鍵字表(如下所示),但我不知道如何按最受歡迎的順序排序。

這裏是我已經擁有的SQL - 它現在只是帶回了任何關鍵字而不是頂級關鍵字。

SELECT product_name,keyword_keyword 
FROM products 
LEFT JOIN keywords ON keyword_pid = product_id 
GROUP BY product_id 

回答

0

這裏是SQLS的進展(帶有示例結果一起)我用於在我所提出的解決辦法:

這裏是關鍵字數:

SELECT k.*, 
     COUNT(k.keyword_keyword) 
FROM keywords k 
GROUP BY k.keyword_pid, 
      k.keyword_keyword 

+------------+-------------+-----------------+--------------------------+ 
| keyword_id | keyword_pid | keyword_keyword | count(k.keyword_keyword) | 
+------------+-------------+-----------------+--------------------------+ 
|   3 |   1 | red    |      3 | 
|   1 |   1 | widgety   |      3 | 
|   9 |   2 | curve   |      1 | 
|   10 |   2 | red    |      2 | 
|   6 |   2 | screwy   |      3 | 
|   12 |   3 | red    |      1 | 
|   7 |   3 | spike   |      2 | 
+------------+-------------+-----------------+--------------------------+ 

我們需要找到每個(keyword_pid,keyword_keyword)對的最大值。 沒有爲這個tried and true idiom

SELECT t1.*, 
     t2.* 
FROM (SELECT k.*, 
       COUNT(k.keyword_keyword) cnt 
     FROM keywords k 
     GROUP BY k.keyword_pid, 
        k.keyword_keyword) t1 
     LEFT JOIN (SELECT k.*, 
         COUNT(k.keyword_keyword) cnt 
        FROM keywords k 
        GROUP BY k.keyword_pid, 
          k.keyword_keyword) t2 
     ON t1.keyword_pid = t2.keyword_pid 
      AND t1.cnt < t2.cnt 

通知書,上面說我重複同樣的SELECT兩次。我假設MySQL緩存第一個SELECT的結果,所以第二個應該非常快。 如果我錯了,我希望有人會消除我的信念。

+------------+-------------+-----------------+-----+------------+-------------+-----------------+------+ 
| keyword_id | keyword_pid | keyword_keyword | cnt | keyword_id | keyword_pid | keyword_keyword | cnt | 
+------------+-------------+-----------------+-----+------------+-------------+-----------------+------+ 
|   3 |   1 | red    | 3 |  NULL |  NULL | NULL   | NULL | 
|   1 |   1 | widgety   | 3 |  NULL |  NULL | NULL   | NULL | 
|   9 |   2 | curve   | 1 |   10 |   2 | red    | 2 | 
|   9 |   2 | curve   | 1 |   6 |   2 | screwy   | 3 | 
|   10 |   2 | red    | 2 |   6 |   2 | screwy   | 3 | 
|   6 |   2 | screwy   | 3 |  NULL |  NULL | NULL   | NULL | 
|   12 |   3 | red    | 1 |   7 |   3 | spike   | 2 | 
|   7 |   3 | spike   | 2 |  NULL |  NULL | NULL   | NULL | 
+------------+-------------+-----------------+-----+------------+-------------+-----------------+------+ 

其中t2.cnt is NULL是包含用於每個(keyword_pid,keyword_keyword)對最大計數的行(這是用於找到最大的成語的一部分)中的行:

SELECT t1.* 
FROM (SELECT k.*, 
       COUNT(k.keyword_keyword) cnt 
     FROM keywords k 
     GROUP BY k.keyword_pid, 
        k.keyword_keyword) t1 
     LEFT JOIN (SELECT k.*, 
         COUNT(k.keyword_keyword) cnt 
        FROM keywords k 
        GROUP BY k.keyword_pid, 
          k.keyword_keyword) t2 
     ON t1.keyword_pid = t2.keyword_pid 
      AND t1.cnt < t2.cnt 
WHERE t2.cnt IS NULL 

+------------+-------------+-----------------+-----+ 
| keyword_id | keyword_pid | keyword_keyword | cnt | 
+------------+-------------+-----------------+-----+ 
|   3 |   1 | red    | 3 | 
|   1 |   1 | widgety   | 3 | 
|   6 |   2 | screwy   | 3 | 
|   7 |   3 | spike   | 2 | 
+------------+-------------+-----------------+-----+ 

其餘部分是比較容易的。首先,我們加入對產品表,所以我們可以看到什麼樣的產品是聯想與哪些關鍵字:

SELECT p.*, 
     t1.* 
FROM (SELECT k.*, 
       COUNT(k.keyword_keyword) cnt 
     FROM keywords k 
     GROUP BY k.keyword_pid, 
        k.keyword_keyword) t1 
     LEFT JOIN (SELECT k.*, 
         COUNT(k.keyword_keyword) cnt 
        FROM keywords k 
        GROUP BY k.keyword_pid, 
          k.keyword_keyword) t2 
     ON t1.keyword_pid = t2.keyword_pid 
      AND t1.cnt < t2.cnt 
     LEFT JOIN product p 
     ON p.product_id = t1.keyword_pid 
WHERE t2.cnt IS NULL 

+------------+--------------+------------+-------------+-----------------+-----+ 
| product_id | product_name | keyword_id | keyword_pid | keyword_keyword | cnt | 
+------------+--------------+------------+-------------+-----------------+-----+ 
|   1 | widget  |   3 |   1 | red    | 3 | 
|   1 | widget  |   1 |   1 | widgety   | 3 | 
|   2 | screw  |   6 |   2 | screwy   | 3 | 
|   3 | nail   |   7 |   3 | spike   | 2 | 
+------------+--------------+------------+-------------+-----------------+-----+ 

以上是解決辦法,如果你想關鍵紐帶。 如果你想擺脫關係(隨機),你可以用另一個GROUP BY這樣做:

SELECT p.*, 
     t1.* 
FROM (SELECT k.*, 
       COUNT(k.keyword_keyword) cnt 
     FROM keywords k 
     GROUP BY k.keyword_pid, 
        k.keyword_keyword) t1 
     LEFT JOIN (SELECT k.*, 
         COUNT(k.keyword_keyword) cnt 
        FROM keywords k 
        GROUP BY k.keyword_pid, 
          k.keyword_keyword) t2 
     ON t1.keyword_pid = t2.keyword_pid 
      AND t1.cnt < t2.cnt 
     LEFT JOIN product p 
     ON p.product_id = t1.keyword_pid 
WHERE t2.cnt IS NULL 
GROUP BY p.product_id 

+------------+--------------+------------+-------------+-----------------+-----+ 
| product_id | product_name | keyword_id | keyword_pid | keyword_keyword | cnt | 
+------------+--------------+------------+-------------+-----------------+-----+ 
|   1 | widget  |   3 |   1 | red    | 3 | 
|   2 | screw  |   6 |   2 | screwy   | 3 | 
|   3 | nail   |   7 |   3 | spike   | 2 | 
+------------+--------------+------------+-------------+-----------------+-----+ 
+0

感謝 - 任何想法如何(在)有效,這可能是什麼? – Chris 2010-10-14 23:04:02

+0

@克里斯:我不知道。我能建議的最好的就是嘗試看看。這裏還有其他人比我知道更多的SQL;也許他們知道更好的方法。 – unutbu 2010-10-15 00:01:00

1

我知道這可能不同,可能更有效地進行,但是這是我的腦海裏是如何把它放下

select a.product_name, b.keyword_keyword, count(*) as keyword_count 
into #temp1 
from products a 
join keywords b on a.product_id = b.keyword_pid 
group by a.product_name, b.keyword_keyword 

select x.product_name, x.keyword_keyword 
from #temp1 x 
where x.keyword_count = (select MAX(keyword_count) from #temp1 
         where product_name = x.product_name)