2015-05-09 48 views
1

我正在建立一個網站,用戶提交屏幕錄像並將其與標籤進行關聯。如何向查找最流行記錄的查詢添加例外情況?

這裏有3個表組成的數據庫:

Screencasts: 

| screencastId | title           | 
|--------------|--------------------------------------------------| 
| CF9S4QZuV30 | Go Programming         | 
| ef-6NZjBtW0 | How to Make Android Apps       | 
| F3WpBsc0QEw | Git & GitHub: Creating a Repository (2/11)  | 
| Ggh_y-33Eso | Learn HTML in 15 Minutes       | 
| GrycH6F-ksY | jQuery Tutorials: Submitting a Form with AJAX | 
| N4mEzFDjqtA | Python Programming        | 
| QRmmISj6Rrw | Learn PHP: Your first file      | 
| WPvGqX-TXP0 | Java Programming         | 
| wz3kElLbEHE | SASS Tutorial         | 
| Xx-XZwJT76w | Setting Up A Development Environment With Bowery | 

Tags: 

| tagName | 
|---------| 
| Android | 
| Bowery | 
| Git  | 
| Go  | 
| Html | 
| Java | 
| jQuery | 
| PHP  | 
| Python | 
| Sass | 


ScreencastTags 

| screencastId | tagName | 
|--------------|---------| 
| CF9S4QZuV30 | Go  | 
| ef-6NZjBtW0 | Android | 
| ef-6NZjBtW0 | Java | 
| F3WpBsc0QEw | Git  | 
| Ggh_y-33Eso | Html | 
| GrycH6F-ksY | jQuery | 
| N4mEzFDjqtA | Python | 
| QRmmISj6Rrw | PHP  | 
| WPvGqX-TXP0 | Java | 
| wz3kElLbEHE | Sass | 
| Xx-XZwJT76w | Bowery | 

該網站允許用戶查看最熱門的標籤:

enter image description here

我用它來查詢確定這9個最熱門的標籤如下:

SELECT t.tagName 
FROM tags t 
JOIN screencastTags m 
    ON m.tagName = t.tagName 
GROUP BY t.tagName 
ORDER BY COUNT(*) DESC, t.tagName DESC 
LIMIT 9 

正如你所看到的,有一個第10菜單項標題爲其他。當點擊時,用戶被顯示屏幕錄像,其標籤是而不是之間的9個最流行的。

我用它來確定這些截屏查詢如下:

SELECT 
    v.screencastId, 
    v.title, 
    GROUP_CONCAT(m.tagName) as tags 
FROM screencasts v 
JOIN screencastTags m 
    ON v.screencastId = m.screencastId 
WHERE m.tagName NOT IN (
    SELECT * FROM (
     SELECT t.tagName 
     FROM tags t 
     JOIN screencastTags m 
      ON m.tagName = t.tagName 
     GROUP BY t.tagName 
     ORDER BY COUNT(*) DESC, t.tagName DESC 
     LIMIT 9) as t) 
GROUP BY v.screencastId 
ORDER BY v.ReferralCount DESC 

不幸的是,這個查詢請求也表現爲我本來希望。它的結果如下表所示:

| screencastId | title     | tagName | 
|--------------|--------------------------|---------| 
| ef-6NZjBtW0 | How to Make Android Apps | Android | 

我想它返回此表:

| screencastId | title     | tagName  | 
|--------------|--------------------------|---------------| 
| ef-6NZjBtW0 | How to Make Android Apps | Android, Java | 

如何實現在這種情況下,預期的結果?

正如您所看到的,子查詢返回9個最受歡迎的標籤,其中包括標籤Java。因爲查詢返回的截屏,其標籤子查詢結果不,標籤的Java不包括在內。它應該是,因爲截屏被標記爲的Android的Java的Android不是9個最熱門的標籤之一,的Java是。

回答

1

如果你想有沒有9個標籤的屏幕類型轉換,那麼邏輯更像是這樣的:

SELECT v.screencastId, v.title, 
     GROUP_CONCAT(m.tagName) as tags 
FROM screencasts v JOIN 
    screencastTags m 
    ON v.screencastId = m.screencastId LEFT JOIN 
    (SELECT t.tagName 
     FROM tags t JOIN 
      screencastTags m 
      ON m.tagName = t.tagName 
     GROUP BY t.tagName 
     ORDER BY COUNT(*) DESC, t.tagName DESC 
     LIMIT 9 
    ) tags9 
    ON m.tagname = tags9.tagname 
GROUP BY v.screencastId, v.title 
HAVING SUM(tags9.tagname IS NOT NULL) = 0; 

這是什麼做的? LEFT JOIN與九個原始標籤匹配標籤(假定數據庫在兩次查詢之間未更新)。聚合是通過屏幕大小寫。 HAVING子句然後檢查是否與九個標籤不匹配。這保證了這9個標籤中沒有一個是來自這個查詢的返回值。

編輯:

哎呀,我想我誤解了這個問題。我以爲你想要的屏幕演員沒有九個標籤。相反,您需要具有附加標籤的屏幕演示的所有標籤。

這實際上是上述查詢的一個小變化。而不是檢查所有標籤是不同的,這檢查任何標籤是不同的。唯一的變化是對HAVING子句:

SELECT v.screencastId, v.title, 
     GROUP_CONCAT(m.tagName) as tags 
FROM screencasts v JOIN 
    screencastTags m 
    ON v.screencastId = m.screencastId LEFT JOIN 
    (SELECT t.tagName 
     FROM tags t JOIN 
      screencastTags m 
      ON m.tagName = t.tagName 
     GROUP BY t.tagName 
     ORDER BY COUNT(*) DESC, t.tagName DESC 
     LIMIT 9 
    ) tags9 
    ON m.tagname = tags9.tagname 
GROUP BY v.screencastId, v.title 
HAVING SUM(tags9.tagname IS NULL) > 0; 
+0

謝謝你的回答,戈登。對此,我真的非常感激。我現在正在測試這個,但是,我得到這個錯誤:'錯誤代碼:1054.'在子句'中的未知列'm.tags'。 –

+0

我將該行更改爲'ON m.tagName = tags9.tagname',並且查詢沒有返回任何行:(。 –

+0

@Angularnoob ...。這表明所有屏幕演員至少有九個原始標籤中的一個 –