[SQL] Nach vorkommender Anzahl sortieren

strolch00

redraft.de
ID: 155297
L
21 April 2006
1.684
72
Hi @all,

habe noch ein Problem und zwar habe ich einen Filter bei mir realisiert (bin noch dabei). Jetzt habe ich folgenden Query:
PHP:
$sql = "SELECT `xxx1`
             , `xxx2`
             , `xxx3`
          FROM `table`
          WHERE `xxx3`
          LIKE '%".@implode('%\' OR \'%', $define_array[(int)$_POST['post_daten']])."%'";
Das define Array schaut wie folgt aus:
PHP:
$define_array = array(1 => array('', '...')
                    , 2 => array('yyy1', 'yyy2', 'yyy3', 'yyy4', 'yyy5', 'yyy6'));

Gibt es jetzt eine Möglichkeit, ohne eine Callbackfunktion in PHP zu schreiben die Ergebnisse nach auftauchender Häufigkeit der Worte yyy... in xxx3 Zu sortieren? Am besten in folgender Reihenfolge:
1. yyy1 (30)
2. yyy1 (25)
3. yyy1 (3), yyy3 (10)
4. yyy2 (2), yyy3 (3), yyy4 (4)
Ich hoffe es ist damit ersichtlich was ich meine.

Mir schwebt das automatische aufsummieren für Ränge aus dem Snippet Thread im Kopf rum aber ich habe keine Idee wie ich es in meinem Fall umsetzen könnte.

Danke an alle.
 
Also erstens habe ich nicht genau verstanden wie die Tabelle aufgebaut ist und was genau als Ergebnis gesucht wird. Warum soll z.B. yyy1 einmal 30 und einmal 25-fach vorkommen und warum soll es Kombinationsmöglichkeiten in xxx3 geben können? Oder sind dann die Kombinationen mit xxx1-3 gemeint?

Wenn du rein die Anzahl der Einträge haben willst, dann machs doch einfach in der Form
Code:
SELECT count(*) as anz
FROM     table
WHERE    xxx3 = '55' OR xxx3 = '56'
GROUP BY xxx3 
ORDER BY anz DESC
Gleichzeitig aber auch die einzelnen Zeilen zu bekommen halte ich für seltsam. Du könntest dir natürlich alle Zeilen raussuchen und dann mit PHP-Mitteln analysieren, doch wie deine gewünschten Ergebnisse im SQL Ergebnis aussehen sollen, kann ich mir gerade nicht so vorstellen. Es müsste ja dann zusätzlich zu den eigentlichen ausgelesenen Spalten noch eine weitere geben, die die Anzahl des jeweiligen xxx3 Eintrages enthält. Aber um das zu füllen fallen mir keine schnellen Wege ein. Sobald die Tabelle sehr groß wird, ist folgender Ansatz nicht mehr zu empfehlen.
Code:
SELECT   xxx1
        ,xxx2
        ,xxx3 as xxx3_
        ,(SELECT count(*) FROM table3 WHERE xxx3 = xxx3_ GROUP BY xxx3) as anz
FROM     table3
WHERE    xxx3 = '55' OR xxx3 = '56'
ORDER BY anz DESC
 
Hmm ja das habe ich bisschen doof umschrieben joschi also bei mir ist es im grunde so da in der tabelle Texte stehen und yyy... stehen für Wörter. Im konkreten fall baue ich gerade wie schon erwähnt nen Filter und da wir ja ein relativ schickes und Jugendgerechtes Projekt wollen lasse ich in dem Zusammenhang jetzt sowas wie S*x, fi...., bum..., usw rausfiltern, deswegen nach der Häufigkeit usw. groupiert.

Aber wenn ich das mit den Kombinationen nicht zurückgeliefert bekommen kann dann ist mir das relativ egal dann highlighte ich die Filterworte damit ich das besser sehen und mir würde es dann reichen nach der Häufigkeit der vorkommen zu sortieren.
Doch wie sagen ich mysql "count(Filterwort) aus Beschreibung as Filterwort"?

*edit wenn es net so perfekt wird ist das net allzutragisch es ist nur ne Adminfunktion, aber die Tabelle wird sehr groß zwar langsam aber irgendwann sind dort 1 mio einträge drin. Diese Einträge werden nicht alle angezeigt aber müssen gescannt werden, wobei das für mysql net das Prob sein sollte.
 
Also sollen die Texte administrativ freigeschaltet werden? Oder sollen die nur administrativ (manuell) rausgeschmissen werden, wenn eben solche Wörter vorkommen?

Einfachste Variante: Die Texte gehen in Rohform in die Datenbank und werden auch so durch die angezeigte Seite ausgelesen, doch dann hauste einfach eine Schleifer per str_replace drüber und ersetzt alle Filterwörter durch drei Sternchen, so muss dann nur die Filterliste angepasst werden, wenn dann statts S*x mal S_E_X geschrieben wird. (gerade mal schauen, ob hier eigentlich auch Filter drin sind :ugly: :mrgreen: )

In der zweiten Variante gekommt die Tabelle der Textinformationen (also wo sowas wie Autor, Uhrzeit usw gespeichert ist) einfach noch eine Spalte "indiziert". Bei jedem Neueintrag wird die dann aktuell bestehende Filterliste abgeprüft und sobald eines der Wörter vorkommt, wird der ganze Eintrag durch dieses Feld gesperrt. Bei der Aktualisierung (meist wohl eine Erweiterung), kannst du dann einfach über alle bestehende Texte die neue Liste laufen lassen (Delta Modus) und entsprechend bestehende Texte mit neu indizierten Wörtern sperren.

Vielleicht wäre auch eine Kombination davon möglich.. Aber jedenfalls würde ich hier keine manuelle Überprüfung empfehlen, weil dann bist du mal zwei Wochen im Urlaub und es gibt im Backend zwar Böse-Wörter-Alarm, aber keine schaut nach.
 
Das macht nix das das Manuell geht ich habe es so gemacht das die gemeldeten Beiträge erstmal aus der Ansicht fliegen. Und erst wenn ich sage jawohl begründet werden die gelöscht oder ich sagen nein nicht begründet dann werden die wieder angezeigt.

Also wegen dem Urlaub habe ich schon mitgedacht^^. Jetzt bräuchte ich nur sonen ORDER BY COUNT damit ich selber im Admin ab und an suchen lassen kann damit evtl. schon teile der News rausgefiltert werden bevor ein User das melden muss.

Und wenn mir einer sagt das geht per SQL net dann habe ich drei Möglichkeiten.
1.so lassen und quälen
2. die Suchalgo anpassen das der nimmer nach LIKE '%bla%' sucht und ich ne bessere Übersicht habe
3. ne Callbackfunktion schreiben die den Array sortiert
 
Und was spricht gegen meine Varianten? Wenn du wohl eh schon eine Blacklist hast, kannst du die doch einfach standardmäßig bei der Anzeige drüber jagen. Wenn dann noch was gefunden wird, kannst du dir ja auch noch zusätzlich eine Meldung zukommen lassen und dann manuell über den Text entscheiden, aber die Besucher sehen an den entsprechenden Stellen schon mal nur die Sternchen.
 
Deine Variante ist schon nicht schlecht, aber ob ich Sternchen machen lasse oder die Blacklist so lasse ist im Grunde egal weil ich so oder so ein aufwändiges Suchmuster schreiben müsste, weil RechtS*xperten sollen ja nicht gefilter werden.

Mir geht es ja jetzt nur in erster Linie darum das ich erstmal ne Vernünftige Liste im Admin hinbekomme, trotz allem logischen Programmierens bleibt die Kontrolle net aus. Die Sterchen Idee habe ich schon aufgegriffen und das sind zwei Zeilen Code das bei mir zu integrieren. Was ich warscheinlich auchmachen werde, danke schonmal für die Idee.
 
Boa Zero das nächste mal hau ich Dich direkt an jetzt hast mir aber eine über den Latz gezogen. Hatte ganz vergessen das ich doch auf der Beschreibung nen Volltext drinn habe :wall: . Jetzt besteht nur eine frage wie meinst Du genau nach Priorität ordnen? Steh ich auf dem Schlauch?
 
mysql vergibt nen scroing wert bei der volltext suche... nach dem kanst du sotieren und erhälst die ergebnisse nach wertigkeit. aber volltext ist für sowas nicht hunder pro geeignet... du schleißt damit zwar solceh probleme wie rechtsexporten aus, aber das ist ebend auch nen nachteil.
 
Ja das mit dem Scoringwert habe ich gerade im Manual gefunden. Danke für den Tipp hoffe mal ich habe es richtig eingebunden. Meine hoffentlich letzen zwei Fragen. Wieso meinst Du das ist ein Nachteil das er das ausschließt? Und wenn es wirklich ein Nachteil bedeutet kann das nichtmal die WITH QUERY EXTENSION beheben richtig? Die such ja nach den Worten dann im zusammenhang aber fungiert nicht wie das LIKE '%bla%'.
 
Ich brauch nochmal nen denkanstoß.
Wie baue ich ne Query einer Volltextsuche mit mehreren Suchworten?
Muss es so lauten?
PHP:
$sql = "SELECT n.`field_one`, n.`field_two`, n.`field_three`, r.`field_four`
            FROM `tabel_one` AS n LEFT JOIN `table:two` AS r USING(field_one)
            WHERE MATCH (n.`field_two`, n.`field_three`) AGAINST (''word1 word2 word3 word4 word5 word6....')";
oder muss es lauten:
PHP:
$sql = "SELECT n.`field_one`, n.`field_two`, n.`field_three`, r.`field_four`
            FROM `tabel_one` AS n LEFT JOIN `table:two` AS r USING(field_one)
            WHERE MATCH (n.`field_two`, n.`field_three`) AGAINST ('word1') 
            OR MATCH (n.`field_two`, n.`field_three`) AGAINST ('word2') 
            OR MATCH (n.`field_two`, n.`field_three`) AGAINST ('word3') 
            OR ...";

Oder ist sowas gar nicht zu realisieren?

*edit:
Beim ersten erhalte ich irgendwie nur scheiße. Und im Manual steht nic genaueres drüber.
 
das erste ist schon richtig... aber häng da mal IN BOOLEAN MODE dran.

PHP:
AGAINST ('word1 word2 word3 word4 word5 word6....' IN BOOLEAN MODE)
 
Oh man das nächste mal lese ich weiter das kenn ich schon allerding habe ich es nur überflogen und die Operatoren gesehn, aber nicht das
mysql manual schrieb:
(kein Operator)

Standardmäßig (also wenn weder + noch - angegeben sind) ist das Wort optional, aber Datensätze, die es enthalten, werden weiter oben einsortiert. Dies ahmt das Verhalten von MATCH() ... AGAINST() ohne den Modifizierer IN BOOLEAN MODE nach.

Danke