webForumDet fria alternativet

Fråga för att plocka ut "oanvända" e-postlistor

Databaser & SQL

7 svar · 477 visningar · startad av MickeA.com

Medlem sedan feb. 20034 441 inlägg
Frågan#1

Hej

Är helt rörigt i huvudet just nu och har ett problem.

Såhär ser mina tabeller ut (MySQL):

[b]email_list[/b]
list_id ([I]INT[/I])
list_name ([I]VARCHAR[/I])

[b]email_list_recipient[/b]
rpt_id ([I]INT[/I])
parent_id ([I]INT[/I], rel. till list_id i ovan)
rpt_user ([I]INT[/I])
rpt_created ([I]DATETIME[/I])
rpt_sent ([I]DATETIME[/I])

Medan jag skickar alla mail bockas man av genom att rpt_sent uppdateras med en tidstämpel (default är NULL).

Nu behöver jag plocka ut alla rader från email_list där inga mail har skickats, alltså oanvända listor.

Jag får inte till det alls, om t.ex. en lista innehåller 10 namn och 9 av dom redan fått mailet, ska listan räknas som förbrukad och ska inte hämtas.

Tacksam för lite hjälp.

Medlem sedan aug. 20039 340 inlägg
#2

Använd mönstret:

SELECT ...
FROM email_list l
LEFT JOIN email_list_recipient r ON l.list_id = r.parent_id
WHERE r.parent_id IS NULL

Idé: Du left-joinar alla mottagare mot listorna, och eftersom det är en left join så får du även med listor utan mottagare. När detta sker blir r.parent_id null eftersom det uppenbart inte finns nägra rader i email_list_recipient att joina. Och det kollar du sedan efter i where-kriteriet.

Medlem sedan feb. 20034 441 inlägg
#3

Nja, nu kanske jag inte förklarade så bra, men finns det en lista i den första tabellen finns det även MINST en mottagare, så parent_id kan inte vara NULL, aldrig.

Det som ställer till det är att bland e-postadresserna som tillhör en lista, så kan rpt_sent antingen vara NULL (inte skickar) eller ett datum. Jag ska bara hämta ut alla listor där rpt_sent är NULL för samtliga mottagare, dvs. listan får inte vara "påbörjad".

Medlem sedan feb. 20034 441 inlägg
#4

Det känns ju som om jag måste räkna antal rader i email_list_recipient och kontrollera att alla rpt_sent är NULL. Då bör jag på något sätt köra en COUNT() på något sätt.

Det som dessutom ställer till det ännu mer - listan får inte redan vara "vald" som lista till ett annat mail.

Men det känns som om jag måste lösa problem #1 innan jag krånglar till allt för mycket.

Medlem sedan feb. 20034 441 inlägg
#5

Nu är jag rätt ute (tror jag):

SELECT
a.list_id, a.list_name,
b.*
FROM email_list a
INNER JOIN email_list_recipient b
ON a.list_id = b.parent_id
WHERE NOT EXISTS (
  SELECT 1 FROM email_list_recipient
  WHERE parent_id = a.list_id
  AND rpt_sent IS NOT NULL
)
GROUP BY b.parent_id
ORDER BY 
a.list_created ASC;

Har testat att sätta alla eller några mottagare per lista som "skickat" och då exkluderas listan, vilket stämmer.

Kan man skriva ovanstående på något vettigare sätt?

Medlem sedan feb. 20034 441 inlägg
#6

MickeA.com skrev:

Kan man skriva ovanstående på något vettigare sätt?

Jo, man kan skippa hela joinen och ändå få ut samma resultat:

SELECT
a.list_id, a.list_name
FROM email_list a
WHERE NOT EXISTS (
  SELECT 1 FROM email_list_recipient
  WHERE parent_id = a.list_id
  AND rpt_sent IS NOT NULL
)
ORDER BY 
a.list_created ASC;
Medlem sedan aug. 20039 340 inlägg
#7

Nja... Det där kan potentiellt vara en prestandadödare. Prova:

SELECT
l.list_id, l.list_name,
FROM email_list l
INNER JOIN email_list_recipient r
ON l.list_id = r.parent_id
GROUP BY l.list_id
HAVING COUNT(r.rpt_sent) = 0

Tricket är dels att köra having, som evalueras efter group by, och dels att räkna count på r.rpt_sent istället för r, vilket räknar antalet rader där r.rpt_sent inte är null.

Medlem sedan feb. 20034 441 inlägg
#8

Det där fungerar ju på precis samma sätt som min, kanon!
Jag var inne från början på att använda COUNT och HAVING men kunde inte komma på hur.

Tack!

249 ms totalt · 4 externa anrop · v20260731065814-full.e96017d9
121 ms — deklarationer (db)
0 ms — hämta statistik (cache)
125 ms — hämta tråd, inlägg och bilagor (db)
119 ms — ändringar (db)