我正在建立一个网站,用户可以在其中提交截屏视频并与之关联。
以下是构成数据库的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个菜单项。点击后,系统会向用户显示其中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 是。
答案 0 :(得分: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
子句检查九个标签是否匹配。这可以保证九个标记中没有一个是此查询返回的值。
编辑:
哎呀,我想我误解了这个问题。我以为你想要没有九个标签的屏幕转换。相反,您希望屏幕转换的所有标签都有其他标签。这实际上是上述查询的一个小变化。而不是检查所有标记是否不同,这将检查任何标记是否不同。唯一的变化是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;