[PHP/MySQL] Query die op verschillende tags filtert.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Karp
  • Registratie: Augustus 2001
  • Laatst online: 22:06
Eens kijken of ik dit duidelijk uit kan leggen.

Ik heb een zoekfunctie nodig die lokaties op 1 of meerdere tags kan soorteren. Voor deze kwestie zijn er 3 relevante tabellen: location, locationtag en tag.
Location bevat de lokatiegegevens en een ID
Locationtag is een koppeltabel die location.id en tag.id koppelt met de toepasselijke waardes locationtag.locationid en locationtag.tagid
Tag is een tabel waarin elke entry bestaat uit een tag.tag en een tag.id


Nu krijg ik het met mijn beperkte sql-kennis wel voor elkaar om lokaties te vinden die op 1 tag matchen:
PHP:
1
$query = "SELECT * FROM location, locationtag, tag WHERE tag.tag like '".$tags[0]."' AND location.id=locationtag.locationid and locationtag.tagid=tag.id";


Maar zodra ik op meerdere tags wil selecteren gaat het me toch echt te ver. Nu heeft een ex-huisgenoot met roestige sql-kennis me ook wel proberen te helpen maar die kwam niet verder dan dit als zijn laatste poging:
PHP:
1
2
3
4
$query = "SELECT * FROM tag".
         "LEFT JOIN (locationtag AS lt) ON (lt.locationid=l.id) ".
         "R JOIN (tag AS t1, tag AS t2) ON (lt. )";
$query.= " WHERE t1.tag LIKE '".trim($tags[0])."' AND t2.tag LIKE '".ucfirst(trim($tags[1]))."'";

En daar volg ik dus al niks meer van.

Indien toepasselijk, het geheel draait verder op Apache en MySQL 5.0.24a en moet op 5.0.18 kunnen werken.
Alle hulp is welkom.

Acties:
  • 0 Henk 'm!

  • mithras
  • Registratie: Maart 2003
  • Niet online
SQL:
1
WHERE tag.tag like '[tagname1]' OR tag.tag like '[tagname2]'
Om dit te bereiken met foreach door je array lopen waar je de tags in zet, en zo de where clausule concateert?

Of doe ik nu iets heel doms :?

Acties:
  • 0 Henk 'm!

  • Mafkees
  • Registratie: Oktober 2003
  • Niet online
Aannemend dat je locatiegegevens wilt adhv een tag kan ik dit bedenken.

SQL:
1
2
3
4
5
SELECT l.*
FROM location l, locationtag lt, tag t
WHERE t.tag IN ('tag1', 'tag2', 'etc..')
AND lt.tagid = t.id
AND l.id = lt.locationid


Trouwens, aan de highlighting te zien is 'location' ook iets in SQL... Misschien handig om daar een andere naam voor te bedenken :P

Acties:
  • 0 Henk 'm!

  • xos
  • Registratie: Januari 2002
  • Laatst online: 12-09 12:41

xos

Mafkees schreef op dinsdag 16 januari 2007 @ 13:45:
Aannemend dat je locatiegegevens wilt adhv een tag kan ik dit bedenken.

SQL:
1
2
3
4
5
SELECT l.*
FROM location l, locationtag lt, tag t
WHERE t.tag IN ('tag1', 'tag2', 'etc..')
AND lt.tagid = t.id
AND l.id = lt.locationid


Trouwens, aan de highlighting te zien is 'location' ook iets in SQL... Misschien handig om daar een andere naam voor te bedenken :P
"IN" werkt net iets anders dan like. Uit het voorbeeld lijkt het alsof hij geen wildcards gebruikt maar misschien staan die al in de variabele.

Maar de topicstarter kan het beste even de sql faq lezen. Dan heeft hij deze query zo in elkaar en vergeet hij het nooit meer natuurlijk ;)

Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

xos schreef op dinsdag 16 januari 2007 @ 13:53:
Maar de topicstarter kan het beste even de sql faq lezen. Dan heeft hij deze query zo in elkaar en vergeet hij het nooit meer natuurlijk ;)
Waar in de FAQ wordt dit probleem opgelost? Ik zie het niet (al kan ik wel een oplossing bedenken).

Rustacean


Acties:
  • 0 Henk 'm!

  • Mafkees
  • Registratie: Oktober 2003
  • Niet online
xos schreef op dinsdag 16 januari 2007 @ 13:53:
[...]


"IN" werkt net iets anders dan like. Uit het voorbeeld lijkt het alsof hij geen wildcards gebruikt maar misschien staan die al in de variabele.

Maar de topicstarter kan het beste even de sql faq lezen. Dan heeft hij deze query zo in elkaar en vergeet hij het nooit meer natuurlijk ;)
Da's waar. Vergt een kleine aanpassing :)

SQL:
1
2
3
4
5
SELECT l.* 
FROM location l, locationtag lt, tag t 
WHERE (t.tag LIKE 'tag1' OR t.tag LIKE 'tag2' OR t.tag LIKE 'etc..')
AND lt.tagid = t.id 
AND l.id = lt.locationid

Dan zou je het gedeelte tussen haakjes moeten genereren in de code.

Acties:
  • 0 Henk 'm!

  • WormLord
  • Registratie: September 2003
  • Laatst online: 21-09 10:10

WormLord

Devver

Tenzij de TS locaties wil vinden die beide gezochte tags hebben. Dan krijg je iets als:
SQL:
1
2
3
4
5
6
7
8
SELECT l.*  
FROM location l, locationtag lt1, tag t1, locationtag lt2, tag t2
WHERE t1.tag LIKE 'tag1'
AND lt1.tagid = t1.id  
AND l.id = lt1.locationid
AND t2.tag LIKE 'tag2'
AND lt2.tagid = t2.id  
AND l.id = lt2.locationid

Acties:
  • 0 Henk 'm!

  • xos
  • Registratie: Januari 2002
  • Laatst online: 12-09 12:41

xos

Manuzhai schreef op dinsdag 16 januari 2007 @ 14:19:
[...]
Waar in de FAQ wordt dit probleem opgelost? Ik zie het niet (al kan ik wel een oplossing bedenken).
In zijn eigen query gebruikt hij al een like om te filteren, dus daar zal het probleem niet in zitten. Verder wordt de suggesie al gegeven dat ie or kan gebruiken om te filteren op meerdere. Dan blijven de joins over als het enige lastige in query van zijn huisgenoot, en dat staat duidelijk in de faq.

Acties:
  • 0 Henk 'm!

  • Karp
  • Registratie: Augustus 2001
  • Laatst online: 22:06
Voor de duidelijkheid, het gaat om een AND-resultaat. En het moet dus mogelijk zijn om op 1, 2, 3... 10 tags te zoeken. Die hoeveelheid is variabel.

Bedankt iig voor alle aandacht zover.

Acties:
  • 0 Henk 'm!

  • Mafkees
  • Registratie: Oktober 2003
  • Niet online
WormLord schreef op dinsdag 16 januari 2007 @ 16:00:
Tenzij de TS locaties wil vinden die beide gezochte tags hebben. Dan krijg je iets als:
SQL:
1
2
3
4
5
6
7
8
SELECT l.*  
FROM location l, locationtag lt1, tag t1, locationtag lt2, tag t2
WHERE t1.tag LIKE 'tag1'
AND lt1.tagid = t1.id  
AND l.id = lt1.locationid
AND t2.tag LIKE 'tag2'
AND lt2.tagid = t2.id  
AND l.id = lt2.locationid
Dat kan dat niet op een makkelijkere manier? Op deze manier moet je namelijk voor elke tag waaraan voldaan moet worden de locationtag en tag tabel nogmaals worden aangegeven.

Ik dacht eerst van je zegt gewoon iets in de vorm van AND t.tag = 'tag1' AND t.tag = 'tag2' maar ik denk niet dat dat gaat werken aangezien je eerst al een selectie maakt en vervolgens nog een selectie gaat maken die op dat moment niet meer kan kloppen.

Volgens mij is iets als dit ook mogelijk:

SQL:
1
2
3
4
5
SELECT l.*
FROM location l, locationtag lt, tag t
WHERE (lt.locationid = l.id AND lt.tagid = t.id AND t.tag LIKE 'tag1')
AND (lt.locationid = l.id AND lt.tagid = t.id AND t.tag LIKE 'tag2')
AND (lt.locationid = l.id AND lt.tagid = t.id AND t.tag LIKE 'etc..')

Acties:
  • 0 Henk 'm!

  • WormLord
  • Registratie: September 2003
  • Laatst online: 21-09 10:10

WormLord

Devver

Mafkees schreef op dinsdag 16 januari 2007 @ 16:33:
[...]

Dat kan dat niet op een makkelijkere manier? Op deze manier moet je namelijk voor elke tag waaraan voldaan moet worden de locationtag en tag tabel nogmaals worden aangegeven.

Ik dacht eerst van je zegt gewoon iets in de vorm van AND t.tag = 'tag1' AND t.tag = 'tag2' maar ik denk niet dat dat gaat werken aangezien je eerst al een selectie maakt en vervolgens nog een selectie gaat maken die op dat moment niet meer kan kloppen.

Volgens mij is iets als dit ook mogelijk:

SQL:
1
2
3
4
5
SELECT l.*
FROM location l, locationtag lt, tag t
WHERE (lt.locationid = l.id AND lt.tagid = t.id AND t.tag LIKE 'tag1')
AND (lt.locationid = l.id AND lt.tagid = t.id AND t.tag LIKE 'tag2')
AND (lt.locationid = l.id AND lt.tagid = t.id AND t.tag LIKE 'etc..')
Dat gaat helaas niet werken. Een combinatie van location, locationtag en tag die aan de eerste conditie vodoet, zal door de tweede en derde condities afvallen. En combinaties die aan de tweede conditie voldoen, voldoen weer niet aan de eerste.

Acties:
  • 0 Henk 'm!

  • InZane
  • Registratie: Oktober 2000
  • Laatst online: 20:14
Mafkees schreef op dinsdag 16 januari 2007 @ 13:45:
Aannemend dat je locatiegegevens wilt adhv een tag kan ik dit bedenken.

SQL:
1
2
3
4
5
SELECT l.*
FROM location l, locationtag lt, tag t
WHERE t.tag IN ('tag1', 'tag2', 'etc..')
AND lt.tagid = t.id
AND l.id = lt.locationid


Trouwens, aan de highlighting te zien is 'location' ook iets in SQL... Misschien handig om daar een andere naam voor te bedenken :P
Hoezo een andere naam :/

SQL:
1
2
3
4
5
SELECT l.*
FROM `location` l, locationtag lt, tag t
WHERE t.tag IN ('tag1', 'tag2', 'etc..')
AND lt.tagid = t.id
AND l.id = lt.locationid


Geen probleem toch?

Acties:
  • 0 Henk 'm!

  • sky-
  • Registratie: November 2005
  • Niet online

sky-

qn nna 👌

Backticks zijn wel een beetje 'vies'.

Idd een andere naam is wel aan te raden :).

don't be afraid of machines, be afraid of the people who build and train them.


Acties:
  • 0 Henk 'm!

  • Karp
  • Registratie: Augustus 2001
  • Laatst online: 22:06
Ligt het aan mij, of helpt het weinig wat er tot nu toe gezegd is? :/

Acties:
  • 0 Henk 'm!

  • WormLord
  • Registratie: September 2003
  • Laatst online: 21-09 10:10

WormLord

Devver

Karp schreef op donderdag 18 januari 2007 @ 23:21:
Ligt het aan mij, of helpt het weinig wat er tot nu toe gezegd is? :/
Het ligt aan jou >:)
Serieus, wat heb je al geprobeerd van de oplossingen die hier aangedragen worden? En wat was het resultaat van die test?

Acties:
  • 0 Henk 'm!

  • Mafkees
  • Registratie: Oktober 2003
  • Niet online
Misschien is UNION select hier een mogelijkheid.. ik weet alleen niet hoe dat werkt :X

Acties:
  • 0 Henk 'm!

  • djc
  • Registratie: December 2001
  • Laatst online: 08-09 23:18

djc

Mafkees schreef op vrijdag 19 januari 2007 @ 14:55:
Misschien is UNION select hier een mogelijkheid.. ik weet alleen niet hoe dat werkt :X
Hmmm, je moet niet zozeer een UNION als wel een INTERSECT hebben. Maar dat bestaat helaas niet. :P

Rustacean

Pagina: 1