[SQL]Join met een exception

Pagina: 1
Acties:

  • mithras
  • Registratie: Maart 2003
  • Niet online
Ik zit met een probleem om in mijn cms blog items op te halen. Ik werk met tags, en nu moet ik alle recente artikelen ophalen die NIET zijn getagged met een bepaald id. Het schema:
code:
1
2
3
4
items       tags         tagged_with
id          id           id
...         name         tag_id
...                      item_id

Daar had ik de volgende query op los gelaten, maar dat werkt niet:
SQL:
1
2
3
4
5
6
SELECT I.id
FROM plugin_blog_items AS I 
LEFT JOIN plugin_blog_tagged_with AS P ON I.id=P.item_id
AND P.tag_id != 6
GROUP BY I.id
ORDER BY I.id DESC
Met wat hulp is er dit uit gekomen:
SQL:
1
2
3
4
5
6
7
SELECT i.id
FROM items i
WHERE 6 NOT IN (
    SELECT t.tag_id
    FROM tagged_with t
    WHERE t.item_id = i.id
)
Dat werkt op zich prima. Maar deze query zal beduidend langzamer worden als er meerdere exceptions bijkomen. In mijn geval zal ik elke keer een nieuwe subquery maken. Het lijkt me duidelijk dat het erg inefficient is, dus vraag ik hier: hoe kan ik artikelen ophalen die (bijvoorbeeld) niet zijn getagged met tag_id 4, 5 en 6?

Alvast bedankt :)

[ Voor 1% gewijzigd door mithras op 15-04-2007 22:11 . Reden: even "werkt niet" toegevoegd ]


  • Morax
  • Registratie: Mei 2002
  • Laatst online: 08:34
SQL:
1
2
3
4
5
6
SELECT I.id
FROM plugin_blog_items AS I 
LEFT JOIN plugin_blog_tagged_with AS P ON I.id=P.item_id
AND P.tag_id != 6
GROUP BY I.id
ORDER BY I.id DESC


Deze kan je toch gewoon ombouwen naar:
SQL:
1
2
3
4
5
6
SELECT I.id
FROM plugin_blog_items AS I 
LEFT JOIN plugin_blog_tagged_with AS P ON I.id=P.item_id
WHERE P.tag_id NOT IN ( 4, 5, 6 )
GROUP BY I.id
ORDER BY I.id DESC


Of snap ik je probleem niet helemaal? :P

What do you mean I have no life? I am a gamer, I got millions!


  • mithras
  • Registratie: Maart 2003
  • Niet online
Uhm, niet helemaal goed uitgelegd: mijn eerste brouwsel werkt niet. Hij hoort dus die met tag_id = 6 niet op te halen, dat doet ie wel gewoon. De tweede (met subqueries) werkt wel, maar dan zou ik met mijn sql gepruts dus dit krijgen:

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT i.id
FROM items i
WHERE 4 NOT IN (
    SELECT t.tag_id
    FROM tagged_with t
    WHERE t.item_id = i.id
)
AND 5 NOT IN (
    SELECT t.tag_id
    FROM tagged_with t
    WHERE t.item_id = i.id
)
AND 6 NOT IN (
    SELECT t.tag_id
    FROM tagged_with t
    WHERE t.item_id = i.id
)
Wat nu niet echt performancegericht is :p

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 08:34
Probeer het volgende anders eens:
SQL:
1
2
3
4
5
SELECT I.id
FROM plugin_blog_items AS I 
LEFT JOIN plugin_blog_tagged_with AS P ON I.id=P.item_id
AND P.tag_id IN ( 4, 5, 6 )
WHERE P.id IS NULL


Ik denk dat ik over het hoofd heb gezien dat een item meerdere tags kan hebben ;)

What do you mean I have no life? I am a gamer, I got millions!


  • mithras
  • Registratie: Maart 2003
  • Niet online
MM, nee. Dat werkt inderdaad ook nog niet :+

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 08:34
mithras schreef op zondag 15 april 2007 @ 21:52:
MM, nee. Dat werkt inderdaad ook nog niet :+
Hmmm, die laatste query die ik je gegeven heb werkt op mijn eigen database wel (wel even aangepast op mijn tabellen dan)...

What do you mean I have no life? I am a gamer, I got millions!


  • mithras
  • Registratie: Maart 2003
  • Niet online
Maar jij hebt nu sowieso "IS IN", terwijl ik het juist wil uitsluiten: artikelen die getagged zijn met een bepaalde tag mogen niet getoond worden. Het moet niet uitmaken dat dat artikel ook is getagged met een andere tag: alsnog mag het item niet getoond worden.

Dat lukt dus wel met die subquery. Nu is alleen mijn probleem performance technisch: ik denk dat voor elke exceptie een subquery toevoegen op zich wel werkt (niet eens getest), maar het lijkt me gewoon vreselijk onhandig om als je 100 tags hebt en er 20 wil uitsluiten dan zo'n query uit te voeren. Ik maak liever gebruik van maximaal 1 subquery, als dat kan tenminste :)

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 08:34
mithras schreef op zondag 15 april 2007 @ 22:17:
Maar jij hebt nu sowieso "IS IN", terwijl ik het juist wil uitsluiten: artikelen die getagged zijn met een bepaalde tag mogen niet getoond worden. Het moet niet uitmaken dat dat artikel ook is getagged met een andere tag: alsnog mag het item niet getoond worden.
Dat klopt, maar in de WHERE clause selecteer ik dus op items waarde join MISLUKT is. Als de join immers gelukt is, dan is P.id gevuld, als de join mislukt, dan is die NULL, en daar selecteer ik ook op, want als de join mislukt is, dan heeft hij geen tag met dat ID ;)

[ Voor 5% gewijzigd door Morax op 15-04-2007 22:20 ]

What do you mean I have no life? I am a gamer, I got millions!


  • mithras
  • Registratie: Maart 2003
  • Niet online
Note to self: beter testen de volgende keer voordat je een behulpzame user teleurstelt

Tnx, ik heb niets gezegd :>

  • Morax
  • Registratie: Mei 2002
  • Laatst online: 08:34
mithras schreef op zondag 15 april 2007 @ 22:26:
Note to self: beter testen de volgende keer voordat je een behulpzame user teleurstelt

Tnx, ik heb niets gezegd :>
Vond het al zo raar. Maar geen probleem hoor, graag gedaan :)

What do you mean I have no life? I am a gamer, I got millions!

Pagina: 1