2016-08-23 21 views
2

我有3个表:Mysql的匹配加权标签

  • 文章(ID,标题......)
  • article_tag(article_id的,TAG_ID)
  • 标签(ID,排序,...)

我发现了一个相关的文章(第具有例如在ID 400)通过与匹配标签的数排序:

SELECT at1.article_id, COUNT(at1.tag_id) AS tag_count 
FROM article_tag AS at1 
INNER JOIN article_tag AS at2 ON at1.tag_id = at2.tag_id 
WHERE at2.article_id = 400 
GROUP BY at1.article_id 
HAVING at1.article_id != 400 
ORDER BY COUNT(at1.tag_id) DESC 
LIMIT 0 , 20 

这工作正常。现在我不想为不同类型的标签增加重量。在表格标签中,有一个名为sort的字段。这是一个int,指定标签的种类。我不想所有种类都有不同的意义。我可以将这些乘数放在不同的表中,或者直接放在SQL代码中(只有6种)。我实际上更喜欢最后的方法,因为那样我可以更容易地调整乘数。我怎样才能做到这一点?

+0

让我明白这一点...你问你是否应该存储一个值,这个值可以改变为硬编码的好的代码......或者作为表中的数据?如果数据可以改变。由谁来,多频繁?尽管什么UI? – xQbert

+0

抱歉不清楚。我的问题是如何编写新的SQL,以利用乘数。乘法器可以是硬编码的,也可以是新表格。但问题是新的SQL ... – user3336208

+0

为什么不向标记表中添加一个名为sort_weight的列或什么......然后当你加入标记表时,它是可访问的。我假设tag.sort只有1个可能的权重。我想我不明白在这个权重阶段的要求,以及它如何用于排序标签和其他数据......有预期结果的示例数据可能会导致 – xQbert

回答

2

可以使用CASE表达

SELECT at1.article_id, 
     SUM(CASE at1.sort 
      WHEN 1 THEN 5 
      WHEN 2 THEN 3 
      ... 
      WHEN 6 THEN 15 
      END) AS tag_weight 
... 
ORDER BY tag_weight DESC 
LIMIT 0, 20 

或者你可以用产生的相关权重的子查询加盟。

SELECT at1.aticle_id, SUM(weights.weight) AS tag_weight 
FROM article_tag AS at1 
INNER JOIN article_tag AS at2 ON at1.tag_id = at2.tag_id 
INNER JOIN (
    SELECT 1 AS sort, 3 AS weight 
    UNION 
    SELECT 2, 3 
    UNION 
    ... 
    SELECT 6, 15 
) as weights ON at1.sort = weights.sort 
WHERE at2.article_id = 400 
GROUP BY at1.article_id 
HAVING at1.article_id != 400 
ORDER BY tag_weight DESC 
LIMIT 0 , 20 
+0

看起来很干净。与案例和子查询的性能有任何差异吗? – user3336208

+0

我不知道。基准和看看。这可能取决于MySQL是否在派生表上创建索引。 – Barmar