Antwort
 
Themen-Optionen
Alt 24.11.2006, 11:08 Nach oben    #1
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 825
Standard MySQL-Abfrage: 1-n-Beziehung mit Versionen

Hi.

In einem CMS hat jede Seite verschiedene Versionen. Diese Seitenversionen liegen in einer MySQL-Tabelle. Jeder Seite sind verschiedene Komponenten zugerdnet. Um nun nicht für jede neue Seitenversion alle Komponenten kopieren zu müssen, würde ich gerne nur die in einer neuen Version veränderten Komponenten kopieren/speichern und bei den anderen Komponenten eben auf die unveränderten Kompoenten-Versionen der letzten Seiten-Versionen zugreifen.

Ich brauche also eine Abfrage, die mir zu einer bestimmten Seite alle Komponenten ausgibt, deren Version kleiner oder gleich der Seitenversion ist. Allerdings von jeder Komponente eben nur die Version mit der höchten Versionsnumer <= Seitenversion.

Ein Beispiel:
Die Startseite hat die Komponenten MlText und News:

Startseite:
page_id = 1
version = 1

Komponenten:
page_id = 1
page_version = 1
component_name = Text
component_id = 10

page_id = 1
page_version = 1
component_name = News
component_id = 11

Dann wird der Text aktualisiert. Es wird also eine neue Komponente "Text" angelegt. Die neue component_id wäre 25. In der Komponenten-Tabelle hab ich dann drei Datensätze:

page_id = 1
page_version = 1
component_name = Text
component_id = 10

page_id = 1
page_version = 1
component_name = News
component_id = 11

page_id = 1
page_version = 2
component_name = Text
component_id = 25

Nun möchte ich eben die Komponenten für die Version 2 auslesen, also Text|25 und News|11:

Gib mir alle Datensätze aus page_components, in denen page_id = 1 und version <= 2, aber je component_name nur genau einen Datensatz und zwar den mit dem höchsten Wert in version.

MySQL-Version: 5.0

Basti

Geändert von Basti (24.11.2006 um 11:14 Uhr).
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2006, 15:50 Nach oben    #2
Lutz
 
Benutzerbild von MrNiceGuy
 
Registriert seit: 14.08.2005
Ort: Nienburg / Weser
Beiträge: 684
Standard

Ui, da müsstest du mal mit GROUP BY experimentieren. Ich weiß nicht genau, ob das zusammen mit ORDER BY funktioniert, denn ich glaube, dass es da ein paar Schwierigkeiten gab. Mit GROUP BY kannst du jedenfalls festlegen, dass jeder component_name nur einmal vorkommen soll im Suchergebnis.
__________________
Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll
MrNiceGuy ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2006, 20:50 Nach oben    #3
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 825
Standard

Vielen Dank. Leider komm ich in die richtung nicht wirklich weiter. Das einzige, das ich bis jetzt hinbekommen hab, ist folgendes:
Code:
SELECT
    name, 
    MAX(id) AS id 

FROM 
    page_components 

WHERE 
    page_id = 1
AND 
    page_version <= 2 

GROUP BY 
    name
Das funktioniert in sofern, dass Komponenten von neuen Versionen auch immer eine höhere ID (da auto_increment) haben. Aber ich finde das ziemlich labil, das Ganze.

Meine bisherige Lösung ist folgende:
Code:
SELECT
    name,
    id 

FROM
    page_components

WHERE
    page_id = 1
AND
    page_version <= 2 

ORDER BY
    page_version
Und dann eben:
PHP-Code:
$aPageComponents = array();

while (
$Record $this->Connection->fetch()) {

    
$aPageComponents[$Record->name] = $Record->id;

Ist halt ziemlicher Quatsch, da die Abfrage bei wirklich jedem Request auf das Page-Modul (und das sind praktisch alle) ausgeführt werden muss. Ich denke, ich werde die Version-Nummer der Komponenten einfach mit-hochzählen. Und beim löschen von Entwürfen einfach wieder runterzählen, sofern die Versionsnummer, die dann erreicht würde nicht schon vergeben ist.

Die Abfrage wäre dann:
Code:
SELECT 
    name,
    id 

FROM
    page_components 

WHERE
    page_id = 1 
AND 
    page_version >= 2 

GROUP BY
    name
Ein weiterer Weg wäre, 3 Tabellen anzulegen: components_archive, page_components und draft_components und dann eben immer rumkopieren. Wäre eigentlich konsequent in die Richtung gedacht, die Last von den Lesezugriffen hin zu den Schreibzugriffen zu verlagern.

Basti

Geändert von Basti (28.11.2006 um 21:48 Uhr).
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2006, 21:31 Nach oben    #4
Lutz
 
Benutzerbild von MrNiceGuy
 
Registriert seit: 14.08.2005
Ort: Nienburg / Weser
Beiträge: 684
Standard

Den Ansatz würde ich sogar unterschreiben Ist zwar auch nicht die feine englische Art, 2 Datenbanken mit quasi der selben Struktur zu verwenden, jedoch ist dies bei vielen, vielen Datensätzen (Beispielsweise wie bei Wikipedia) mit Sicherheit deutlich performanter.
__________________
Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll
MrNiceGuy ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 28.11.2006, 22:02 Nach oben    #5
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 825
Standard

Problem dabei sind halt de IDs der Komponenten. Jetzt hab ich ein auto_increment-Feld und jede neue Komponente bekommt eben auch eine neue ID von der Seite verpasst. Das ist zumindest bislang der Plan, denn bislang (ohne Versionierung) hab ich die Komponenten selbst ihre IDs schreiben lassen.

Ich weiß noch nicht so ganz, was hier ein geschicker Weg ist. Auf der einen Seite möchte ich, dass bei Veränderugen von Seiten auch nur von den Komponenten neue Versionen erstellt werden, die auch wirklich verändert wurden (wobei ich befürchte, dass das garnicht so leicht umzusetzen ist, da mitunter mehrere Komponenten ein und die selbe Tabelle verändern können - so gibt es eine Tabelle "offers" und sowohl auf den Institut-Seiten lassen sich deren Angebote verändern, als auch auf den Angebote-Seiten lassen sich die Institute angeben, die die Leistung anbieten). Auf de anderen Seite, soll die Komponenten-Programmierung so einfach, wie möglich sein. Ich würde die Versionierung dort also gerne weitgehend raushalten. Etwas so:

Code:
Page an Component:
"Gibt es beim aktuellen Request an Komponente x was zu verändern?"

Wenn ja:
Page: erzeuge neuen Komponenten-Eintrag -> neue ID

Page -> Component:
"Kopiere Komponente von alte ID nach neue ID"
"Bearbeite Komponente mit neuer ID"
Hab aber noch keine wirklich zufriedenstellende Lösung gefunden. Morgen sollte der Part eigentlich stehen und eine Hand voll Module umgebaut sein... Sieht also so aus, das ich erstmal "pfuschen" (besser: hinbiegen, Kompromisse eingehen) muss, bis sich eine anständige Lösung abzeichnet.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 29.11.2006, 06:47 Nach oben    #6
Lutz
 
Benutzerbild von MrNiceGuy
 
Registriert seit: 14.08.2005
Ort: Nienburg / Weser
Beiträge: 684
Standard

Ui, die Reihenfolge ist aber nicht die Schönste... Was ist denn, wenn jemand eine Veränderung der Seite machen möchte, dann aber doch abbricht? Dann hast du einen Zustand der Seite gleich 2 mal in der DB stehen, sehr unschön. Ich würde eher sagen, dass sobald auf den Speichern-Button gedrückt wird erst der Datensatz erzeugt wird undzwar dann direkt aus den Daten, die geschickt wurden, das erspart auch das Kopieren.
__________________
Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll
MrNiceGuy ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 29.11.2006, 10:54 Nach oben    #7
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 825
Standard

Zitat:
Zitat von MrNiceGuy Beitrag anzeigen
Ui, die Reihenfolge ist aber nicht die Schönste... Was ist denn, wenn jemand eine Veränderung der Seite machen möchte, dann aber doch abbricht? Dann hast du einen Zustand der Seite gleich 2 mal in der DB stehen, sehr unschön.
Eben nicht, da der Kopier- und Editierauftrag ja nur an die Komponente geht, wenn auch wirklich was verändert wurde. Das ist ja auch genau der Punkt, um den es geht. Andernfalls fürde ich einfach für jeden neuen Entwurf alle Komponenten aus der aktuellen Version klonen und diese dann einfach mit den entsprechenden Request-Teilen füttern.

Das Problem ist so, wie es im Moment angedacht ist eben, dass nur die Komponente selbst herausfinden kann, ob der Request was verändern will und das wiedrum ist halbwegs aufwändig bzw. bläht die Komponenten eigetlich unnötig auf.

Eine andere Möglickeit wäre, das irgendwie mit Widgets zu lösen, denen ein Zustand zugeteilt wird, der sich beim Sumbit eben verändert (oder auch nicht). Das wäre natürlich das geschickteste, denn dann würde ich die Komponente erst garnicht ansprechen, wenn nichts verändert wurde.

Zitat:
Ich würde eher sagen, dass sobald auf den Speichern-Button gedrückt wird erst der Datensatz erzeugt wird undzwar dann direkt aus den Daten, die geschickt wurden, das erspart auch das Kopieren.
Das Problem ist, dass das Formular auf mehrere Panels aufgeteilt ist, die unter anderem auch File-Uploads enthalten. Klar, am liebsten würde ich einen Prozess anlegen, der einen Kontainer enthält, in den alle Requests incl. Uploads gespeichert werden. Ich denke, den Weg werd ich auch in Zukunft einschlagen, aber für den Moment ist das zu aufwändig (garbage collection, Konflikte bzw. gemeinsames Arbeiten an einem Entwurf (ist ja ein Mehrbenutzersystem) etc.)

Mein Problem ist grad, dass es Komponenten gibt, für die ich gerade keine Versionierung hinbekomme, die sich nicht auf die Seitenversion beziehen, sondern auf z.B. die Gruppe der Seite. Mir fällt nicht recht ein, wie ich das geschickt lösen kann bzw. zumindest dem Benutzer leicht transparent machen kann.

... dicke Gedankenwolken quillen aus meinem Büro.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 29.11.2006, 12:05 Nach oben    #8
Lutz
 
Benutzerbild von MrNiceGuy
 
Registriert seit: 14.08.2005
Ort: Nienburg / Weser
Beiträge: 684
Standard

Hmm... Ich weiß nicht, ob ich das jetzt richtig verstanden habe, aber wäre es eventuell auch möglich ein BLOB-Feld zu erzeugen, in dem du dann mittels XML + ZIP die alten Versionen speicherst und nur die aktuellste in den Feldern selber lässt? So hast du nach wie vor nur einen Datensatz pro Seite und die aktuellste ist immer im "Vordergrund". Solltest du auf die alten Versionen zugreifen müssen, kannst du das BLOB-Feld auslesen und entsprechend ändern!?
__________________
Paradox ist, wenn jemand für seinen Alkoholkonsum geradestehen soll
MrNiceGuy ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Alt 29.11.2006, 13:22 Nach oben    #9
Bastian Fenske
 
Registriert seit: 04.01.2006
Ort: Kassel
Beiträge: 825
Standard

Ich glaub, das ist nicht wirklich einfacher.

Ich habs auch grad auf die beschriebene Methode zumindest für die einfache Text-Komponente hinbekommen:
PHP-Code:
<?php

class Mod_MlText_Controller extends ModuleController
{
    protected 
$Manager;
    protected 
$iComponentId;
    public    
$MlText;

    public function 
init($iId)
    {
        
$this->iComponentId $iId;
        
$this->Manager $this->Persistence->getManager('MlText');
    }

    public function 
action_display()
    {
        
$this->setView('Display');
        
$this->recieveMlText();
        return 
$this->success();
    }

    public function 
updateRequired()
    {
        
$this->recieveMlText();
        return 
$this->MlText->content !== $this->Request->get('pagecomponent.Text.content');
    }

    public function 
action_edit()
    {
        
$this->recieveMlText();
        
$this->setView('EditForm');
        return 
$this->success();
    }
    public function 
action_update()
    {
        
$this->recieveMlText();
        
$this->MlText->update($this->Request->get('pagecomponent.Text'));
        return 
$this->success();
    }
    
    public function 
action_create()
    {
        
$aComponentData = array(
            
'id' => $this->iComponentId,
            
'content' => $this->Request->get('pagecomponent.Text.content')
        );

        
$this->Manager->create($aComponentData);
        return 
$this->success();
    }

    protected function 
recieveMlText()
    {
        
$this->MlText $this->Manager->get($this->iComponentId);
    }
}
(Anstatt dem kompletten $Request wird den Komponenten bald ein Request-Filter übergeben, so dass der Zugriff nurnoch über $this->Request->get('content'); laufen wird.)

Im Page_Controller siehts ausgedünnt so aus:
PHP-Code:

        $aComponents 
$this->Request->get('pagecomponent');

        if (!
is_array($aComponents))
            
$aComponents = array();

        foreach (
$aComponents as $sComponent => $aValues) {

            
$aComponent   $this->Page->getComponent($sComponent);

            
$sModule      $aComponent['module'];
            
$sComponentId $aComponent['id'];
            
$sPageVersion $aComponent['page_version'];

            
$this->$sComponent $this->addChild(
                
$sModule,
                
$sComponentId,
                
$this->Page
            
);

            if (
$this->$sComponent->updateRequired()) {
                if (
$aComponent['page_version'] < $this->Page->version) {

                    
$this->Page->createNewComponentVersion($sComponent);
                    
$aComponent $this->Page->getComponent($sComponent);
                    
$sComponentId $aComponent['id'];

                    
$this->$sComponent $this->addChild(
                        
$sModule,
                        
$sComponentId,
                        
$this->Page
                    
);
                    
$this->$sComponent->create();

                } else {

                    
$this->$sComponent->update();
                }
            }
        } 
Mal sehen, ob ich damit durchkomme. *g

Ich werde das Dingens übrigens, so der Plan, Anfang bis Mitte nächsten Jahres unter einer Public Licence veröffentlichen.

Basti
Basti ist offline  
Add Post to del.icio.usBookmark Post in TechnoratiDiesen Beitrag zu Mister Wong hinzufügen!
Mit Zitat antworten
Antwort

Lesezeichen


Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)
 
Themen-Optionen

Forumregeln
Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Ähnliche Themen
Thema Autor Forum Antworten Letzter Beitrag
MySQL Abfrage Bedingung julien Datenbanken 4 06.08.2006 00:44
ssh tunnel zu einer mysql datenbank beny_mcde Datenbanken 4 07.06.2006 16:05
MySQL 5.1 kommt in die Beta-Phase Ben Nachrichten 1 02.03.2006 14:31
MySQL: Abfrage aus zweiter Tabelle. Sebastian PHP-Programmierung 6 16.12.2005 00:01
MySQL Abfrage bei 2 Spalten Julied64 Datenbanken 5 06.12.2005 19:05


Alle Zeitangaben in WEZ +2. Es ist jetzt 14:52 Uhr.


Powered by vBulletin® Version 3.7.3 (Deutsch)
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44