[PHP + MySQL] selecteren op basis van lijst criteria

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • chronozphere
  • Registratie: Juli 2006
  • Laatst online: 16-12-2020
Hi,

Ik wil een zoeksysteem maken dat gebaseerd is op zoeken met criteria. De gebruiker geeft een lijstje met criteria waaraan de resultaten moeten voldoen en vervolgens word de database doorzocht. :) Voorbeeld:
Gewenste eigenschappen (1, 2)

Tabel met items die elk een willekeurig aantal eigenschappen hebben
A: 1, 2, 3, 4
B: 2, 3, 5, 6, 8, 7
C: 4, 2, 1
D: 2, 4, 5, 1
E: 3, 5, 7, 1, 8
F: 6, 2, 7, 1

Resultaat:
A, C, D, F
Ik kan me voorstellen dat dit eenvoudig te doen is. Toch weet ik niet hoe ik dit het beste aan kan pakken.

Je kan hiervoor "sets" gebruiken, maar dan zit je met een limiet van 64 criteria. Daarnaast zou het prettig zijn als elk criterium een ID kan zijn binnen de table van criteria (De beheerder moet nieuwe zoek-criteria kunnen toevoegen). Performance is ook belangrijk. De lijst van te doorzoeken items kan vrij groot worden.

Heeft iemand hier ideeen over? linkjes, query voorbeelden, etc zijn zeer welkom.

Alvast bedankt! :)

Acties:
  • 0 Henk 'm!

  • Alm4riC
  • Registratie: Februari 2005
  • Laatst online: 17-09 22:16
Ik denk dat je dit het beste kan aanpakken door een koppeltabel te maken.
Dus in de eerste tabel zet je de "te vinden objecten"
code:
1
2
3
4
1 - A
2 - B
3 - C
4 - D


De tweede tabel wordt je koppeltabel, waarin je de "te vinden objecten" koppelt aan de criteria.
code:
1
2
3
4
5
6
7
8
9
10
// het 2de getal is het criteria & het eerste getal het id van het "te vinden object"
1 - 1
1 - 2
2 - 2
2 - 4
3 - 1
3 - 2
3 - 3
3 - 4
4 - 3


In je vierde derde tabel staan dan je criteria. Hier kun je gemakkelijk een criteria aan toevoegen. En het blijft makkelijk om criteria te verwijderen.
code:
1
2
3
4
1 - criteria omschrijving
2 - criteria omschrijving
3 - criteria omschrijving
4 - criteria omschrijving


Ik hoop dat het een beetje duidelijk is en je er wat aan hebt!
Succes :*)

//edit typo

Acties:
  • 0 Henk 'm!

  • Trucker Her
  • Registratie: Juni 2009
  • Niet online

Trucker Her

Someone ate my cookie :(

Ik mis de 3rde tabel?

Gestoord word je toch...


Acties:
  • 0 Henk 'm!

  • chronozphere
  • Registratie: Juli 2006
  • Laatst online: 16-12-2020
Thnx voor je reactie. :)

Dan nog een belangrijke vraag: Wat voor query moet ik gebruiken om te zoeken op een aantal criteria?
Neem aan dat je gaat zoeken in die koppeltabel.

Alvast bedankt. ;)

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
chronozphere schreef op woensdag 24 februari 2010 @ 22:27:
Dan nog een belangrijke vraag: Wat voor query moet ik gebruiken om te zoeken op een aantal criteria?
Neem aan dat je gaat zoeken in die koppeltabel.
Dan nog een belangrijke vraag: Wat heb je al geprobeerd?
Neem aan dat je dat gedaan hebt.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Alm4riC
  • Registratie: Februari 2005
  • Laatst online: 17-09 22:16
Probeer eens iets met joins (inner, left of right).
http://www.google.nl/sear...s+tutorial&meta=&aq=f&oq=

Acties:
  • 0 Henk 'm!

  • chronozphere
  • Registratie: Juli 2006
  • Laatst online: 16-12-2020
Thanks voor de reacties. ;)

Heb inmiddels gekeken naar joins en ik zie dat ze mijn probleem mogelijk zouden kunnen oplossen. Ik weet alleen nog niet hoe ik ze dan pricies moet gebruiken.

Ik kan dus een self-join doen om zo op twee criteria te testen. Ik heb als voorbeeld een table gemaakt met campings en hun eigenschappen.

> CampingID
> Eigenschap (b.v "water", "zwembad", "schaduw").

Stel, ik ben op zoek naar een camping met schaduwplaatsen en watervoorziening (kraantje bij staanplaats).
Dan zou de volgende query een begin kunnen zijn:

code:
1
SELECT * FROM `properties_table` A, `properties_table` B WHERE A.property= "water" AND B.property = "schaduw"


Ik krijg dit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
1   water   3   schaduw
2   water   3   schaduw
3   water   3   schaduw
5   water   3   schaduw
1   water   2   schaduw
2   water   2   schaduw
3   water   2   schaduw
5   water   2   schaduw
1   water   6   schaduw
2   water   6   schaduw
3   water   6   schaduw
5   water   6   schaduw


Ik begrijp dat ik hier de informatie uit kan halen die ik nodig heb (een camping die aan beiden eisen voldoet). Ik weet alleen niet hoe ik dit moet bereiken. :?

Daarnaast ga ik in de problemen komen als ik op meerdere eigenschappen zoek (> 16). Heb namelijk begrepen dat SQL vaak niet meer dan 16 joins in één query aankan.

Kan iemand me verder op weg helpen?

Thanks!

[ Voor 5% gewijzigd door chronozphere op 26-02-2010 21:21 ]


Acties:
  • 0 Henk 'm!

  • BrZ
  • Registratie: Maart 2000
  • Laatst online: 00:11

BrZ

Dit wil je niet doen dmv self-joins, dat wordt te omslachtig als je veel criteria hebt.

Ik zou het doen dmv een GROUP BY en dan met HAVING een controle doen op het aantal eigenschappen waar het aan moet voldoen:

SQL:
1
2
3
4
5
SELECT camping
FROM koppeltabel
WHERE property IN (1,2,4)
GROUP BY camping
HAVING COUNT(*)=3


Als het aan alle criteria moet voldoen moet je op het eind dus het aantal criteria neerzetten, als het bv aan 2 van de 3 moet voldoen kan dat hiermee ook (en dan dus >2 gebruiken).

Stuk efficienter dan 16 of meer self-joins ;)

Acties:
  • 0 Henk 'm!

  • chronozphere
  • Registratie: Juli 2006
  • Laatst online: 16-12-2020
Net even die query getest in PHPMyAdmin en hij werkt! 8)

Onwijs bedankt! :)

Acties:
  • 0 Henk 'm!

  • jlrensen
  • Registratie: Oktober 2000
  • Laatst online: 19-09 00:04

jlrensen

plaatjes vullen geen gaatjes

Oplossing van BrZ werkt overigens alleen (correct) als een eigenschap niet twee maal bij hetzelfde product kan voorkomen. Als F als eigenschappen 1,1,3 heeft, gaat het fout.

Men moet het denken bijbrengen, niet wat al gedacht is. ~C. Gurlitt


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

chronozphere schreef op zaterdag 27 februari 2010 @ 15:22:
Net even die query getest in PHPMyAdmin en hij werkt! 8)

Onwijs bedankt! :)
Weet je ook hoe en waarom die query werkt? Gewoon klakkeloos overnemen hebben we allemaal niets aan. ;)
jlrensen schreef op zondag 28 februari 2010 @ 00:49:
Oplossing van BrZ werkt overigens alleen (correct) als een eigenschap niet twee maal bij hetzelfde product kan voorkomen. Als F als eigenschappen 1,1,3 heeft, gaat het fout.
Ehm...waarom? Ik zie het probleem niet?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
NMe schreef op zondag 28 februari 2010 @ 01:14:
Ehm...waarom? Ik zie het probleem niet?
Dat gaat ervan uit van dat een combinatie (item,eigenschap) meerdere keren kan voorkomen. Dat lijkt me enkel alleen mogelijk als de keys niet goed staan, maar het is inderdaad theoretisch mogelijk, dat moet ik toe geven. :p Overigens is een join waarschijnlijk wel sneller - zie crisp in "Relatie postings met user" (hetzelfde probleem met andere benamingen - topic=item, user=eigenschap).

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • chronozphere
  • Registratie: Juli 2006
  • Laatst online: 16-12-2020
Weet je ook hoe en waarom die query werkt? Gewoon klakkeloos overnemen hebben we allemaal niets aan. ;)
Nou, ik heb dus wel de moeite genomen om te kijken hoe GROUP BY en HAVING werken. ;)

Het komt erop neer dat er eerst een aantal rows geselecteerd worden met WHERE, waarbij de expressie geëvalueerd word voor elke row. Deze worden vervolgens gegroepeerd m.b.v GROUP BY, op basis van een gegeven kolom. Daarna wordt de expressie in HAVING los gelaten op de lijst van groepen.

Ik heb ook even gekeken naar het probleem van jlrensen. Ik dacht aan iets als DISTINCT, maar dat kan niet aangezien dat een speciale vorm van GROUP BY is, die we al in onze query hebben zitten. Subqueries bieden uitkomst:

code:
1
2
3
4
5
SELECT * FROM 
  (SELECT DISTINCT * FROM `search_table`) AS d 
WHERE property IN (1, 2) 
GROUP BY camping 
HAVING COUNT(*) = 2

Acties:
  • 0 Henk 'm!

  • BrZ
  • Registratie: Maart 2000
  • Laatst online: 00:11

BrZ

jlrensen schreef op zondag 28 februari 2010 @ 00:49:
Oplossing van BrZ werkt overigens alleen (correct) als een eigenschap niet twee maal bij hetzelfde product kan voorkomen. Als F als eigenschappen 1,1,3 heeft, gaat het fout.
Klopt, maar ik ging er van uit dat de combinatie camping/eigenschap uniek zou zijn.
pedorus schreef op zondag 28 februari 2010 @ 02:32:
Overigens is een join waarschijnlijk wel sneller - zie crisp in "Relatie postings met user" (hetzelfde probleem met andere benamingen - topic=item, user=eigenschap).
Ik vraag me af of een join nog steeds sneller is bij heel veel eigenschappen, zou ik eens moeten testen.
Pagina: 1