[MySQL] Join nur für höchste ID einer Tabelle

flaschenkind

Well-known member
ID: 118459
L
20 April 2006
4.507
337
Titel: Naja, mir viel nichts besseres ein, und weiß auch nciht, wie ich das Problem besser so kurz beschreiben soll ;)

Also ich habe folgende Query:
PHP:
SELECT `clixx_kampagnen`.`id`, `clixx_kampagnen`.`text`, `clixx_kampagnen`.`vergutung`, `clixx_kampagnen`.`bzeit` FROM `clixx_kampagnen` LEFT JOIN `clixx_clicked` ON (`clixx_kampagnen`.`id`=`clixx_clicked`.`kampagne` AND `clixx_clicked`.`reload_ende`>'.time().' AND `clixx_clicked`.`reload_ende`=0 AND `clixx_clicked`.`user`=123) WHERE `clixx_clicked`.`user` IS NULL AND `clixx_kampagnen`.`ubrig`>0 AND `clixx_kampagnen`.`what`=1

Die Query liest mir alle Kampagnen aus, bei denen die Reloadsperre abgelaufen ist (reload_ende < time()). Die mit noch aktiver Reloadsperre, und die, die keine Reloadsperre haben und dadurch immer gesperrt bleiben, mit der reload_ende=0 bleiben immer raus. Klappt auch so weit. Allerdings sind in der Tabelle clixx_clicked alle Klicks geloggt. Also würde der, wenn da zweimal ein Reloadeintrag ist, einmal mit aktiver Reload, einmal mit inaktiver Reload, trotzdem den Banner anzeigen. Das will ich unterbinden, aber ich weiß nciht genau, wie ich das machen soll. Ich hab schon einiges getestet, aber das ging auch alles nicht, was ich mir auch gedacht hatte. Ich hoffe hier hat einer ne Idee :)

Ich möchte nicht die Einträge anderweitig auslagern, oder ne 2. Query machen. In einer wäre es am schönsten. Ich hoffe auf Euch :D
 
Was immer du in der Abfrage rausbekommen willst. Es dürfte nicht klappen, weil die Abfrage in sich wiedersprüchlich ist!

`clixx_clicked`.`reload_ende`>'.time().' AND `clixx_clicked`.`reload_ende`=0
Du schreibst in deiner Erklärung, dass reload_ende < time() sein soll. In der Abfrage steht aber ein >. Und gleichzeitig soll es auch noch 0 sein? Entweder es ist eine Zeit oder 0, aber es kann nie beides gleichzeitig (AND) sein.

`clixx_clicked`.`user`=123
und
`clixx_clicked`.`user` IS NULL
Der User kann natürlich nicht gleichzeitig 123 und NULL sein.

Kannst du mal erklären, warum reload_ende 0 sein soll? Ich dachte, dass ist ein Datumswert. Wenn du Kampagnen (für User) sperren und freischalten willst, dann solltest du das nicht über ein Reload-Datum machen, sondern ein extra Feld einbauen, z.B. status. (Oder habe ich das falsch verstanden.)

Ich würde das ganze Problem etwas anders angehen. Ich würde nicht die Kampagnen suchen, bei denen die Reload-Sperre abgelaufen ist, sondern die Kampagnen auswählen, bei denen keine Reload-Sperre für den User existiert. Dazu sind zwei Schritte erforderlich:
1. Alle abgelaufenen Reloads aus der Tabelle löschen (das hält auch die Datenmenge in Grenzen).
2. Jetzt alle Kampagnen suchen, bei denen für den User kein Reload existiert.
Das ganze geht auch über ein Left Join, ist aber einfacher zu machen. Sollte etwa so aussehen:
PHP:
SELECT k.`id`, k.`text`, k.`vergutung`, k.`bzeit` FROM `clixx_kampagnen` k LEFT JOIN `clixx_clicked` c ON (k.`id`=c.`kampagne` AND c.`user`=123) WHERE c.Primärschlüssel IS NULL
Evtl. mit dem User noch etwas rumprobieren.

Wenn du nur ein Ergebnis brauchst, dann kannst du das mit einem 'LIMIT 1' am Ende erreichen. Evtl. vorher noch ne Sortierung einfügen.
 
Was immer du in der Abfrage rausbekommen willst. Es dürfte nicht klappen, weil die Abfrage in sich wiedersprüchlich ist!
Nein.

Du schreibst in deiner Erklärung, dass reload_ende < time() sein soll. In der Abfrage steht aber ein >. Und gleichzeitig soll es auch noch 0 sein? Entweder es ist eine Zeit oder 0, aber es kann nie beides gleichzeitig (AND) sein.
So filter ich die Einträge raus und bekomme nur die, wo das zutrifft :p

und
Der User kann natürlich nicht gleichzeitig 123 und NULL sein.
Durch das =123 in dem JOIN schließ ich die aus und bekomm nur die, wo der User nicht gesetzt ist.

Kannst du mal erklären, warum reload_ende 0 sein soll? Ich dachte, dass ist ein Datumswert. Wenn du Kampagnen (für User) sperren und freischalten willst, dann solltest du das nicht über ein Reload-Datum machen, sondern ein extra Feld einbauen, z.B. status. (Oder habe ich das falsch verstanden.)
Jein. Also es soll eine begrenzte und eine unbegrenzte Reload geben. Die begrenzten bekommen da gespeichert, wann sie wieder klicken können, die unbegrenzten können dann halt nicht wieder geklickt werden. Nur wenn jetzt ein begrenzter abgelaufen ist, und dann klickt man wieder - befindet sich also wieder in der Reloadsperre - erkennt die Query einen trotzdem noch als ausserhalb der Reloadsperre, da der erste gefundene Eintrag genommen wird, und das ist nicht der neuste.

1. Alle abgelaufenen Reloads aus der Tabelle löschen (das hält auch die Datenmenge in Grenzen).
[/QUOTE]
Löschen will ich nciht, das soll dann nur gemacht werden, wenns wirklich nicht anders geht. Und dann brauch ich hier keine Hilfe, dann müsst ja nur hingehen und alle abgelaufenen Einträge löschen ;)

2. Jetzt alle Kampagnen suchen, bei denen für den User kein Reload existiert.
Mach ich ja schon, nur beachte ich dabei noch die Reloadsperre direkt, damit nichts gelöscht werden muss ;)

Wenn du nur ein Ergebnis brauchst, dann kannst du das mit einem 'LIMIT 1' am Ende erreichen. Evtl. vorher noch ne Sortierung einfügen.
Ich brauche alle Kampagnen angezeigt, wo der User ausserhalb einer Reloadsperre ist, also geht das nicht ;)
 
Was immer du in der Abfrage rausbekommen willst. Es dürfte nicht klappen, weil die Abfrage in sich wiedersprüchlich ist!
Nein.
Doch! :ugly:

So filter ich die Einträge raus und bekomme nur die, wo das zutrifft :p
[...]
Durch das =123 in dem JOIN schließ ich die aus und bekomm nur die, wo der User nicht gesetzt ist.
Mag ja sein, dass du das tun willst, aber du tust es nicht...
Wieso sollte ein Left Join Datensätze ausschließen?

Eigentlich willst du doch Folgendes: Zu jedem Datensatz in der Kampagnen-Tabelle suchst du die zugehörige Zeile aus der Clicked-Tabelle mit der höchsten ID.
Beim MSSQL-Server würde ich das wohl mit einem Subselect lösen, ob das bei MySQL auch so ohne Weiteres funktioniert, hab ich jetzt nicht im Kopf, aber grundsätzlich müsste irgendwas in der Art herauskommen:

PHP:
SELECT    `clixx_kampagnen`.`id`
        , `clixx_kampagnen`.`text`
        , `clixx_kampagnen`.`vergutung`
        , `clixx_kampagnen`.`bzeit`
FROM      `clixx_kampagnen`
LEFT JOIN `clixx_clicked`
  ON      `clixx_clicked`.`id`          = ( SELECT  MAX(`id`)
                                            FROM    `clixx_clicked`
                                            WHERE   `kampagne`      = `clixx_kampagnen`.`id`
                                              AND   `user`          = '.$gesuchteruser.'
                                          )
WHERE     `clixx_kampagnen`.`ubrig`     > 0
  AND     `clixx_kampagnen`.`what`      = 1
  AND     (     `clixx_clicked`.`reload_ende` < '.time().'
            AND `clixx_clicked`.`reload_ende` > 0
            OR  `clixx_clicked`.`reload_ende` IS NULL
          )

Ich unterstelle dabei jetzt, dass die Tabelle clixx_clicked eine Spalte "id" hat, die einen für die Tabelle eindeutigen Schlüssel beinhaltet. Die Abfrage (ohne Where-Klausel) liefert mir nun alle Kampagnen aus der Kampagnen-Tabelle und ergänzt bei denen, bei denen passende Einträge in der Clicked-Tabelle existieren, die entsprechenden Infos (jeweils aus der Clicked-Zeile mit der höchsten ID). Aus dem Ergebnis suche ich mir dann alle Zeilen, bei denen reload_ende in der Vergangenheit liegt, aber nicht 0 ist, oder bei denen reload_ende NULL ist (das sind dann die, für die ich keine Zeile in der Clicked-Tabelle gefunden habe).
 
Eigentlich willst du doch Folgendes: Zu jedem Datensatz in der Kampagnen-Tabelle suchst du die zugehörige Zeile aus der Clicked-Tabelle mit der höchsten ID.
Ne, ich will die Kampagnen, für die der User keine Reload hat ;)
Hab jetzt aber ne Lösung, was anscheinend auch funktioniert. Werd das jetzt mal eingehend testen, und dann mal weiter sehen. Deins werd ich auch nochmal testen ;)
Thx schonmal :)