如何选择我的内容以及随附的所有标签?

时间:2011-07-03 20:08:23

标签: php mysql sql

我已经非常努力地拥有一个规范化的数据库,并且目前有三个这样的表 -

  1. 内容(c)
  2. content_tags(ct)
  3. tags(t)
  4. 我在这里要做的是选择一些行并返回所有与之关联的标记。目前,它只出于某种原因返回一个标签。

    以下是我正在使用的代码:

       SELECT *, 
              GROUP_CONCAT(t.tag) AS tags
         FROM content AS c 
    LEFT JOIN category AS ca ON c.cid = ca.cid 
    LEFT JOIN contenttags AS ct ON c.smid = ct.smid 
    LEFT JOIN tags AS t ON ct.tid = t.tid 
    LEFT JOIN users AS u ON c.uid = u.uid
        WHERE (t.tag IN ('tag1', 'tag2', 'tag3'))
     GROUP BY c.smid
    

    它返回如下内容:

    • CID
    • 含量
    • URL
    • 标签(但只有一个而不是多个)

3 个答案:

答案 0 :(得分:2)

这是你的问题。

WHERE (t.tag IN ('$tagArray'))

考虑以下两个表达式做不同的事情:

WHERE (t.tag IN (1,2,3,4))
WHERE (t.tag IN ('1,2,3,4'))

引用的字符串尽管看起来是多个整数的列表,但实际上是单个值。在整数上下文中,MySQL读取前导数字(在这种情况下为“1”),并在找到非数字后忽略后面的任何内容。


我所说的是查询两边的引号都令人困惑。 $ tagArray的值是tag1','tag2','tag3吗?或者是'tag1','tag2','tag3'

通常,通过查看SQL来排除SQL问题,而不是查看生成SQL的PHP​​代码。请在您的问题中显示最终的SQL查询,不要让我们猜测$ tagArray的值是什么。


PS:这可能与您的问题无关,但您在需要INNER JOIN的地方使用LEFT JOIN。

答案 1 :(得分:0)

我相信您需要在tags表上进行第二次连接 - 一次用于WHERE子句,另一次用于返回所有相关结果。未经测试,但试试这个:

SELECT c.*,t2.*,ca.*,ct.*,u.* GROUP_CONCAT(t.tag) AS tags
FROM content AS c
LEFT JOIN category AS ca ON c.cid = ca.cid
LEFT JOIN contenttags AS ct ON c.smid = ct.smid
LEFT JOIN tags AS t2 ON ct.tid = t2.tid
LEFT JOIN users AS u ON c.uid = u.uid
JOIN tags AS t ON ct.tid = t.tid
WHERE (t.tag IN ('$tagArray'))
GROUP BY c.smid

这将为每个相关标记返回一个单独的行,因此您必须在客户端代码中合并这些结果,或者如果您希望单行上的所有标记(作为数组),则可能使用GROUP_CONCAT()

答案 2 :(得分:0)

您的意思是找到所有内容及其所有标签,其中至少有一个标签位于$tagArray

   SELECT c.*, ca.*, u.*, 
          GROUP_CONCAT(t.tag) AS tags
     FROM content AS c 
LEFT JOIN category AS ca ON c.cid = ca.cid 
     JOIN contenttags AS ct ON c.smid = ct.smid 
     JOIN tags AS t ON ct.tid = t.tid 
LEFT JOIN users AS u ON c.uid = u.uid
    WHERE EXISTS ( SELECT *
                   FROM contenttags ct2
                     JOIN tag t2
                       ON t2.tid = ct2.tid
                   WHERE ct2.smid = c.smid
                     AND ct2.tag IN ('$tagArray')
                 )
 GROUP BY c.smid

这些LEFT JOIN也可能会变成内部JOIN,而不会丢失任何结果。试试吧。除非category.cidcategory.uid字段可以包含NULL个值。在这种情况下,请保留相关的LEFT JOIN