[英]How do I add an exception to a query that finds the most popular records?
我正在建立一個網站,用戶可以在該網站上提交截屏視頻並將其與標簽關聯。
這是構成數據庫的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 |
該網站允許用戶查看9個最受歡迎的標簽:
我用來確定這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個菜單項名為Other 。 單擊時,將向用戶顯示其標簽不在 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不是。
如果您希望屏幕投射不包含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
正在將標簽與9個原始標簽匹配(假設兩個查詢之間的數據庫尚未更新)。 聚合情況取決於屏幕情況。 然后, HAVING
子句檢查是否與這9個標記不匹配。 這保證了這9個標簽都不是該查詢的返回值之一。
編輯:
糟糕,我想我誤解了這個問題。 我以為您想要沒有這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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.