2016-08-23 3 views
2

passend Ich habe 3 Tabellen:Mysql gewichtete Tags

  • Artikel (id, Titel, ...)
  • article_tag (article_id, tag_id)
  • Tag (id, sortieren, ...)

fand ich einen verwandten Gegenstand (Artikel mit dem ID 400 im Beispiel), indem sie mit der Anzahl der passenden Tags Reihenfolge:

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 

Das funktioniert gut. Jetzt möchte ich den verschiedenen Arten von Tags Gewicht hinzufügen. Im Tabellen-Tag gibt es ein Feld mit dem Namen sort. Dies ist ein int, der die Art des Tags angibt. Ich möchte alle möglichen Bedeutungen haben. Ich kann diese Multiplikatoren in eine andere Tabelle setzen oder direkt in den SQL-Code schreiben (es gibt nur 6 Sortierungen). Ich würde eigentlich die letzte Methode bevorzugen, weil ich dann die Multiplikatoren leichter einstellen kann. Wie kann ich das machen?

+0

Lassen Sie mich das klarstellen ... Sie fragen, ob Sie einen Wert speichern sollten, der als fest codierter Quellcode geändert werden könnte ... oder als Daten in einer Tabelle? wenn die Daten geändert werden können. von wem, wie oft? und was UI? – xQbert

+0

Entschuldigung für Unklarheiten. Mein Problem ist, wie man das neue SQL schreibt, um die Multiplikatoren zu verwenden. Die Multiplikatoren können entweder fest codiert oder in einer neuen Tabelle sein. Aber das Problem ist die neue SQL ... – user3336208

+0

Warum nicht eine Spalte zu Tag-Tabelle namens sort_weight oder etwas hinzufügen ... und dann, wenn Sie sich an die Tag-Tabelle anschließen, ist es zugänglich. Ich nehme an, dass ein tag.sort nur 1 mögliche Gewichtung hat. Ich denke, ich verstehe nicht die Anforderung in dieser Phase der Gewichte und wie es in Bezug auf Tags und die anderen Daten verwendet wird ... Beispieldaten mit erwarteten Ergebnissen clairify – xQbert

Antwort

2

können Sie einen CASE Ausdruck

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 

verwenden, oder Sie können mit einer Unterabfrage verbinden, die die zugehörigen Gewichte erzeugt.

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

Sieht sehr sauber aus. Gibt es Unterschiede in der Leistung mit Fall und Unterabfrage? – user3336208

+0

Ich weiß es nicht ohne weiteres. Benchmark es und sehen. Es hängt wahrscheinlich davon ab, ob MySQL einen Index für die abgeleitete Tabelle erstellt. – Barmar