Facebook Pinnwand realisieren

  • Hallo,

    Ich versuche gerade die Facebook Pinnwand durch ein SQL Statement zu realisieren. Dabei habe ich 3 Tabellen (als Beispiel) :

    Beitrag (userid, Zeit)
    Gefaelltmir (userid, Zeit)
    Foto (userid, Zeit)

    Die Tabellen sind natürlich nur zu testzwecken derartig aufgebaut um euch zu zeigen was ich machen möchte: und zwar möchte ich ähnlich wie bei Facebook für eine userid die letzten 5 Aktionen darstellen. D.h. Nicht 5 Beiträge, 5 gefällt mir und 5 Fotos sondern die letzten 5 Aktionen aus allen Tabellen (natürlich nach der Zeit absteigend).

    Momentan setze ich 3 sqls ab, schreibe das Ergebnis in ein Array, sortiere das in php und lösche alle Indizes die größer als 5 sind. Das ist aber weder schön noch perfomant. Außerdem möchte ich nun einen Offset wert mit einbeziehen -> um eine pagination zu realisieren ( zeige zuerst letzten 1-5 Aktionen und dann 6-10 usw). Am liebsten würde ich das alles in einem query realisieren..*

    Bin für jeden Tipp dankbar! :)

  • lol, um den Algorithmus der Pinnwand zu kopieren wirst du etwas länger brauchen, glaubs mir...


    War schon überrascht, Teron hilft? Mal den Post anzeigen lassen und nun ist die Welt wieder in Ordnung :roll:


    Was du vorhast ist eigtl. gar nicht so schwer.
    So in etwa dürfts hinhauen (in der Annahme, dass die userid die gleiche sein soll und du auch danach filtern willst):

    SQL
    SELECT userid, zeit
    FROM ( 
      (SELECT userid, zeit FROM Beitrag)
        UNION ALL
      (SELECT userid, zeit FROM Gefaelltmir)
      ORDER BY zeit DESC
      LIMIT 0,5
    ) as actions
    WHERE userid = 1


    (ansonsten kannst die WHERE klausel einfach weglassen)

    Für die 3te Tabelle brauchst du natürlich noch ein UNION ALL.

    //P.S.
    hier ist der Datensatz mit dem ich getestet hab:

    2 Mal editiert, zuletzt von Grevas (11. Dezember 2011 um 23:58) aus folgendem Grund: bekacktes forum kann kein UNIX. \r\n ftw?

  • Hallo grevas

    Vielen dank für deine Hilfe! Soviel ich weiß funktioniert Union aber nur wenn die Tabellen die gleiche Anzahl von Spalten + den gleichen Datentyp haben. Das ist aber bei mir nicht der Fall (nur im Beispiel oben zum leichteren Verständnis..

    Wie bekomme ich das jetzt hin?

    Danke!

  • Ok, fehlende Spalten kann ich mit NULL-Werten befüllen. Soweit so gut.
    Ausserdem habe ich herausgefunden, dass ich bei jedem einzelnen Select-Statement die Where
    Klausel brauche.

    Ein Problem habe ich noch: die Performance.
    Ich lese ja nun alle Sätze des Users (wegen der Where, die ich bei jedem Select hinzugefügt habe)
    aus, füge die Ergebnisse zusammen und setze dann meinen Offset und Limit Wert. Funktionieren
    tut das super, aber wenn der User pro Tabelle mehrere tausend Sätze hat und ich nur Offset = 0
    und Limit = 2 will, sucht er ja trotzdem erst mal alle oder nicht?

    Wie kann ich das Problem umgehen?

  • Denke auch an die Indizes deiner Tabellen. Je performanter Du diese setzt, umso schneller können Abfragen auch laufen. Außerdem hängt das hängt vom Datenbanksystem ab. Bei Oracle kann man für sowas prima temporäre Tabellen nutzen, bei MySQL (ISAM) eher nicht.

  • Da gebe ich dir Recht, threadi!
    Aber ist das wirklich nicht anders möglich, als erst alle Zeilen zu lesen und dann einzuschränken?
    Bin für jede Idee dankbar!

  • Ich realisiere soetwas mit einer zusätzlichen Tabelle `dashboard` => `id` (Pk, AI), `referredTable` (Index), `referredPkValue`(Index), `datetimeOfAdd`(Index)
    Wird jetzt ein neuer Kommentar auf die Pinnwand geschrieben wird der ganz normal gespeichert, zusätzlich aber ein Eintrag in `dashboard` erstellt mit Tabellenname der Kommentar-Tabelle, ID des neues Kommentars und dem Zeitpunkt.

    Das ist zwar etwas zusätzlich Datenhaltung, aber Speicherplatz kostet heute nix mehr, die Abfrage wird viel schneller als so nen UNION-Gedöns über X-Tabellen und vor allem kann ich im Dashboard jegliche Aktivität festhalten die passiert, also jeden Neueintrag für jede Tabelle der Datenbank.
    Andernfalls müsstest du, sobald irgendeine Tabelle dazu kommt die im Dashboard angezeigt werden soll, gleich wieder deine UNION-Abfrage erweitern.

    Hier mal ein älterer Thread von mir zu etwa dem Thema:
    http://www.php.de/software-desig…dern-n-1-a.html

    "Programming today is a race between software engineers
    striving to build bigger and better idiot-proof programs,
    and the universe trying to build bigger and better idiots.
    So far, the universe is winning."
    Rick Cook

  • Hallo Sinnlos,

    interessanter Ansatz :) Und wie würde dann die Abfrage aussehen?
    Sollte ja mit einem Join machbar sein. Nur ich weiß grad nicht,
    wie ich das hinbekomme, weil der Name der Tabelle ja in einer Spalte
    steht..

    Wie würdest du das aufbauen?

    Danke sehr!

  • Ich frage für mein Dashboard die eigentlichen Einträge gar nicht selber ab, sondern speichere in meiner dashboard-Tabelle eine zusätzliche Spalte mit einem Kommentar. Bei einem neuen Pinnwandeintrag kann das z.B. sowas sein "Manfred Mustermann hat an deine Pinnwand geschrieben: [ersten 80 Zeichen des Beitrags]..."
    D.h. ich benötige den Eintrag auf den referenziert wird nicht für mein Dashboard.
    Andernfalls müsstest du wohl zusätzlich SELECTs raushauen um die Einträge selber noch zu holen. Bei vielen Tabellen mit vielen Datensätzen die beobachtet werden sollen und einer im Verhältnis gesehen kleinen Ergebnismenge bleibt das trotzdem performanter.

    "Programming today is a race between software engineers
    striving to build bigger and better idiot-proof programs,
    and the universe trying to build bigger and better idiots.
    So far, the universe is winning."
    Rick Cook

  • Ah ok :) Dabei stellt sich mir jetzt aber die Frage:
    Nehmen wir an ich möchte die Tabellen, auf die referenziert wird, mit einbeziehen.
    Dann verwende ich ja schätzungsweiße einen Join.

    Nur stellt sich mir dabei die Frage: Wie baue ich das SQL-Statement auf, denn der
    Tabellenname der Referenz-Tabelle steckt ja in einer Spalte.
    Ist das überhaupt in einer SQL-Abfrage möglich?


  • Nur stellt sich mir dabei die Frage: Wie baue ich das SQL-Statement auf, denn der
    Tabellenname der Referenz-Tabelle steckt ja in einer Spalte.
    Ist das überhaupt in einer SQL-Abfrage möglich?


    Ich wüßte keine Möglichkeit dafür. Daher meinte ich ja, dass du dann gegebenenfalls noch zusätzliche SELECTs auf die referenzierten Tabellen raushauen müsstest.

    "Programming today is a race between software engineers
    striving to build bigger and better idiot-proof programs,
    and the universe trying to build bigger and better idiots.
    So far, the universe is winning."
    Rick Cook

  • Wie gesagt: sowas ginge mit temporären Tabellen. Bei MySQL werden diese jedoch anders gehandhabt als bei MySQL, in diesem Fall für MySQL eher nachteilig. Eine solche temporäre Tabelle würde die Daten aus echten Tabellen bereitstellen und diese dem abrufenden Programm anbieten. Somit ist die Idee von SinnlosS durchaus praktikabel, aber eben nur mit temporären Tabellen die dynamisch gefüllt werden.