我已经非常努力地拥有一个规范化的数据库,并且目前有三个这样的表 -
我在这里要做的是选择一些行并返回所有与之关联的标记。目前,它只出于某种原因返回一个标签。
以下是我正在使用的代码:
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
它返回如下内容:
答案 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.cid
或category.uid
字段可以包含NULL
个值。在这种情况下,请保留相关的LEFT JOIN
。