Avatar billede pitzen Nybegynder
07. april 2009 - 08:54 Der er 10 kommentarer og
1 løsning

Meget indviklet query

Hej eksperter,

Jeg har nu siddet flere timer og kæmpet med en query, som jeg nu har givet lidt op over for.

Jeg vil nu prøve at forklare problemet.
Jeg sender nyhedsbreve ud til mine brugere, men jeg er kun interesseret i at sende til dem, som gider læse mine breve. Derfor vil jeg gerne fjerne inaktive brugere fra maillisten. Mit kriterie for at fjerne dem er, hvis de ikke har læst ét af det seneste fem breve jeg har sendt dem.

Strukturen i "send_log" er:
id | time | time_open | bruger_id | brev_id | read

Hvor read=1 hvis de har læst brevet. "time" er de tidspunkt jeg har sendt brevet, "time_open" er tidspunktet de har åbnet det, resten giver nok sig selv :)

Er det nogen der kan gennemskue en løsning på dette? Jeg vil kort sagt gerne have et udtræk med alle de bruger_id'er som ikke har læst ét af de fem seneste breve de har fået sendt.

Mvh
P
Avatar billede majbom Novice
07. april 2009 - 09:37 #1
SELECT COUNT(id) FROM send_log WHERE read='1' AND bruger_id='$id' ORDER BY time LIMIT 5

hvis antallet er under 5 har de ikke læst alle breve

hvordan gemmer du time? som datetime?
Avatar billede SebastianN Nybegynder
07. april 2009 - 09:39 #2
Jeg går ud fra at du ud over "send_log" har en tabel med brugere, "bruger" og en tabel med breve, "brev".

Vælg alle brugere som IKKE har en registrering i "send_log":

SELECT * FROM bruger WHERE bruger.id NOT IN (SELECT bruger_id FROM send_log)

En alternativ version med LEFT JOIN:

SELECT * FROM bruger LEFT JOIN send_log ON bruger.id = send_log.bruger_id WHERE send_log.bruger_id IS NULL

Begge forespørgsler er i T-SQL. De burde kunne bruges næsten direkte i MySQL.
Avatar billede SebastianN Nybegynder
07. april 2009 - 09:40 #3
Mit svar baserer sig på at du vil kende alle de brugere, som ALDRIG har læst et af dine nyhedsbreve.
Avatar billede pitzen Nybegynder
07. april 2009 - 09:48 #4
splazz >> Det vil kræve at jeg løber hele listen igennem en while-løkke, hvilket jeg helst vil undgå - men det er klart et alternativ! Jeg gemmer time som datetime ja.

Sebastian >> Ja, det kan jeg se. Men jeg vil gerne fjerne brugere, der er faldet fra senere hen ligeledes. Derfor skal det være i betragtning af de seneste 5 breve. Som du forslår at fjerne dem der aldrig har læst nogen breve, er ikke en god ide. Da vil alle nye brugere blive fjernet og evt. gamle brugere der endnu ikke har fået sendt et brev.
Avatar billede SebastianN Nybegynder
07. april 2009 - 09:54 #5
Nu forstår jeg. Har du en sendt-dato i din "brev" tabel?
Avatar billede SebastianN Nybegynder
07. april 2009 - 10:04 #6
Mit sidste spørgsmål besvarede sig selv... din sendt-dato er "time" i send_log.

Nyt forsøg:

Vælg alle brugere som IKKE optræder blandt de brugere, der har læst
nyhedsbreve, som er sendt siden 01-04-2009

SELECT * FROM bruger WHERE bruger.id NOT IN
    (SELECT send_log.bruger_id FROM sendlog
    WHERE send_log.time > '01-04-2009' AND
    send_log.read = 1)

Så kan du præcisere på dato i stedet for sidste 5.
Avatar billede pitzen Nybegynder
07. april 2009 - 10:36 #7
Jeg vil allerhelst have en løsning med 5 breve - da jeg sender breve ud med forskelligt tidsmellemrum og til forskellige segmenter og derfor vil denne løsning ikke kunne laves særlig dynamisk.
Avatar billede SebastianN Nybegynder
07. april 2009 - 10:51 #8
Vælg alle brugere som IKKE er iblandt de brugere, som har læst et af de seneste 5 breve. Den forudsætter af dine primære nøgler er fortløbende ints. Jeg tager forbehold for fejl, skriver den i hånden... men den skulle være der nu.

SELECT * FROM bruger
WHERE bruger.id NOT IN
    (
        SELECT send_log.bruger_id FROM sendlog
        WHERE send_log.read = 1 AND
        send_log.brev_id IN
            (
                SELECT brev.id FROM brev
                ORDER BY brev.id DESC LIMIT 5
            )
    )
Avatar billede pitzen Nybegynder
07. april 2009 - 11:44 #9
Tak for endnu et forslag.

Dette vil dog heller ikke virke optimalt, da alle brugere ikke modtagere alle breve. Derfor vil nogen blive mærket inaktive trods de måske kun har modtaget ét brev (grundet segmentering).

Din løsning vil også udvælge brugere der har modtaget under fem breve, hvilket gør at de endnu ikke har fået chancen for at læse det 5. brev.
Avatar billede SebastianN Nybegynder
07. april 2009 - 12:06 #10
Hrm. Ja.

Brugere som har fået tilsendt mindst 5 ulæste breve... men den tager ikke højde for, at det skal være de seneste 5 som er ulæste.
Om ikke andet, så kan den måske være inspiration.

SELECT bruger.id FROM bruger
INNER JOIN send_log ON bruger.id = send_log.bruger_id
WHERE send_log.read = 0
GROUP BY bruger.id
HAVING COUNT(send_log.brevid) >= 5
Avatar billede pitzen Nybegynder
29. juni 2010 - 18:37 #11
lukker
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester