0

我有三个单独的表 - pagestagspages_tagged- 分别包含页面内容标签名称ids以及带有标签 id的页面 id

我正在尝试设置一个 MySQL 查询,该查询采用搜索词并检查现有标签,找到匹配的标签 ID,并返回带有所述标签的所有页面 - 我已经很好地完成了。但是,当我尝试进一步扩展它以在 pages 表的 title 列中查询匹配字符串时,事情变得有点糟糕。

我的SQL如下:

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
       DATE_FORMAT( pages.dateAdded,  '%M %e, %Y' ) AS dateAdded, 
       pages.viewcount, pages.sessionId 
FROM tags JOIN pages_tagged ON tags.id = pages_tagged.tag_id 
JOIN pages ON pages_tagged.page_id = pages.randomId 
WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%')
ORDER BY dateAdded DESC

我知道这里的操作顺序是非常错误的,但是我无法用正确的方法来修改这个查询以使其正常工作。

谁能指出我明显的错误?

编辑:

当查询运行时,为了澄清“肚皮上扬”,它是“成功的”。但是,不会返回任何行。

如下修改 WHERE 子句以隔离 pages.title LIKE '%ovechkin%' 永远不会导致返回的行,无论搜索词是什么。

WHERE (pages.title LIKE '%ovechkin%')

编辑2:

下面的示例数据。

pages
╔════╦════════════════════════╦═════════════════════╦══════════╦═══════════╗
║ id ║         title          ║      dateAdded      ║ randomId ║ viewcount ║
╠════╬════════════════════════╬═════════════════════╬══════════╬═══════════╣
║ 57 ║ Ovechkin looping about ║ 2013-04-07 19:26:06 ║ xp3rvju  ║         5 ║
╚════╩════════════════════════╩═════════════════════╩══════════╩═══════════╝

tags
╔════════╦══════════╗
║ id     ║ tag      ║
╠════════╬══════════╣
║     25 ║ ovechkin ║
╚════════╩══════════╝

pages_tagged
╔══════════════════╗
║ tag_id | page_id ║
╠══════════════════╣
║ 25 | xp3rvju     ║
║ 25 | mpbjbk6     ║
╚══════════════════╝

编辑3:

如建议的那样, aRIGHT JOIN开始pages.title工作。修改后的查询是:

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
   DATE_FORMAT( pages.dateAdded,  '%M %e, %Y' ) AS dateAdded, 
   pages.viewcount, pages.sessionId 
FROM tags RIGHT JOIN pages_tagged ON tags.id = pages_tagged.tag_id 
RIGHT JOIN pages ON pages_tagged.page_id = pages.randomId 
WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%')
ORDER BY dateAdded DESC    

剩下的一个问题是,如果一个页面在其标题和相关标签中具有相同的搜索词,它将返回两次。我尝试将其修改为包含DISTINCT在选择中,如下所示,但这对返回的行没有影响。

SELECT DISTINCT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
   DATE_FORMAT( pages.dateAdded,  '%M %e, %Y' ) AS dateAdded, 

编辑4:

也可以包括防止重复的最终解决方案 - GROUP BY.

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
   DATE_FORMAT( pages.dateAdded,  '%M %e, %Y' ) AS dateAdded, 
   pages.viewcount, pages.sessionId 
FROM pages 
LEFT JOIN pages_tagged ON pages.randomId = pages_tagged.page_id 
LEFT JOIN tags ON tags.id = pages_tagged.tag_id 
WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%')
GROUP BY pages.randomId
ORDER BY dateAdded DESC    
4

2 回答 2

0

尝试以下操作:

 select * from
   (SELECT tags.id as tid, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
           DATE_FORMAT( pages.dateAdded,  '%M %e, %Y' ) AS dateAdded, 
           pages.viewcount, pages.sessionId 
    FROM tags JOIN pages_tagged ON tags.id = pages_tagged.tag_id 
    JOIN pages ON pages_tagged.page_id = pages.randomId 
    WHERE tags.tag = 'thang' 
    union
    ( SELECT tags.id as tid, pages_tagged.page_id, pages.id, pages.randomId, pages.title, 
           DATE_FORMAT( pages.dateAdded,  '%M %e, %Y' ) AS dateAdded, 
           pages.viewcount, pages.sessionId 
     FROM pages JOIN pages_tagged on pages_tagged.page_id = pages.randomId
     JOIN tags ON tags.id = pages_tagged.tag_id   
     WHERE           pages.title LIKE '%thang%'
    )
  ) as a
    ORDER BY a.dateAdded DESC

这样,它将在“正确”页面之后选择第一个“正确”标签。

于 2013-04-08T15:24:38.690 回答
0

了解连接的一般工作原理很重要,这里有一个简单的解释: http: //www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html

由于您正在寻找OR与标题匹配的标签,我猜您想使用 aRIGHT JOIN作为关系,因为此查询不会返回任何未标记的页面。

目前,如果您有一个带有标题ovechkin但没有标签的页面,您将无法使用此查询找到它。

这就是我尝试过的:http ://sqlfiddle.com/#!2/c25c5/2

通常,构建查询的方式意味着您将获取所有标记,然后加入任何标记的页面。没有该WHERE子句的行为如下:

执行正常JOIN只会返回标记页面,如果数据库中没有标记,您将不会得到单行。

LEFT JOIN即使没有标记任何页面,使用 a方法您也可以获得每个标记的结果。

使用RIGHT JOIN意味着您将获得所有页面的所有结果行,即使没有标签或没有标签页面。

对于所有这些,任何没有数据的字段都将被填充为空。

我建议将查询更改为此(为了便于阅读,删除了某些字段):

SELECT tags.id, pages_tagged.page_id, pages.id, pages.randomId
FROM pages 
LEFT JOIN pages_tagged ON pages.randomId = pages_tagged.page_id 
LEFT JOIN tags ON tags.id = pages_tagged.tag_id

WHERE (tags.tag = 'ovechkin' OR pages.title LIKE '%ovechkin%')

如果同一页面有多个标签,您将获得不止一次。

于 2013-04-08T15:36:19.947 回答