Multiple Checkboxes sql query
Hallo,
Met mijn opleiding ben ik bezig met een webshop met daarin de volgende vraag:
Ik en mijn groepsgenoten willen bij de categorie pagina meerdere categorieën kunnen filteren en dit in de sql query kunnen plaatsen.
Heeft iemand een idee hoe dit moet?
Met mijn opleiding ben ik bezig met een webshop met daarin de volgende vraag:
Ik en mijn groepsgenoten willen bij de categorie pagina meerdere categorieën kunnen filteren en dit in de sql query kunnen plaatsen.
Heeft iemand een idee hoe dit moet?
Ik dacht aan zoiets
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$sql = "SELECT FROM shop WHERE title LIKE '%" . $_POST['q'] . "%'";
if(isset($_POST['cat'])){
$i=0;
foreach($_POST['cat'] AS $cat){
$sql .= ($i == 0) ? ' AND ' : ' OR ';
$sql .= 'cat = "' . $cat . '"';
$i++;
}
}
echo $sql;
/* Output: SELECT FROM shop WHERE title LIKE '%PHP%' AND cat = "boeken" OR cat = "cds" */
}
?>
<form method="POST">
<input type="search" name="q" /><br />
<label>Boeken</label>
<input type="checkbox" name="cat[]" value="boeken" />
<label>CD's</label>
<input type="checkbox" name="cat[]" value="cds" />
<label>Games</label>
<input type="checkbox" name="cat[]" value="games" />
<button>Zoeken</button>
</form>
if($_SERVER['REQUEST_METHOD'] == 'POST'){
$sql = "SELECT FROM shop WHERE title LIKE '%" . $_POST['q'] . "%'";
if(isset($_POST['cat'])){
$i=0;
foreach($_POST['cat'] AS $cat){
$sql .= ($i == 0) ? ' AND ' : ' OR ';
$sql .= 'cat = "' . $cat . '"';
$i++;
}
}
echo $sql;
/* Output: SELECT FROM shop WHERE title LIKE '%PHP%' AND cat = "boeken" OR cat = "cds" */
}
?>
<form method="POST">
<input type="search" name="q" /><br />
<label>Boeken</label>
<input type="checkbox" name="cat[]" value="boeken" />
<label>CD's</label>
<input type="checkbox" name="cat[]" value="cds" />
<label>Games</label>
<input type="checkbox" name="cat[]" value="games" />
<button>Zoeken</button>
</form>
Edit:
Kleine aanpassing in het script
Aanpassing betreft reactie van Erwin
Aanpassing betreft reactie van Erwin
Gewijzigd op 18/12/2013 15:05:39 door Michael -
Behalve dan dat je niet AND moet gebruiken in je query, maar OR. Anders kan je wel op "boeken" AND "games" zoeken, maar dan krijg je waarschijnlijk niet veel terug, aangezien het meestal een boek of game is.
Daarbij zou ik ook geen LIKE gebruiken, tenzij je erg onvoorstandig meerdere categorie opties in 1 databaseveld propt.
Correctie: de LIKE was voor de titel, niet voor de categorie.
Correctie: de LIKE was voor de titel, niet voor de categorie.
Gewijzigd op 18/12/2013 14:53:42 door Erwin H
Erwin H op 18/12/2013 14:52:38:
Behalve dan dat je niet AND moet gebruiken in je query, maar OR. Anders kan je wel op "boeken" AND "games" zoeken, maar dan krijg je waarschijnlijk niet veel terug, aangezien het meestal een boek of game is.
Daarbij zou ik ook geen LIKE gebruiken, tenzij je erg onvoorstandig meerdere categorie opties in 1 databaseveld propt.
Correctie: de LIKE was voor de titel, niet voor de categorie.
Correctie: de LIKE was voor de titel, niet voor de categorie.
Je hebt gelijkt. De eerste moet AND zijn, maar de daaropvolgende moet OR zijn. De code is hierop aangepast.
Bedankt voor de reactie, de checkboxes werken nu. Maar het probleem is dat producten die in meerdere categorieën plaats vinden niet meer getoond worden als er twee categorieën worden aangeklikt.
Dus bijvoorbeeld een flesje water die in de kerst en in de zomer verkocht kan worden, wordt niet getoond. Dus niet alle andere producten die of alleen in de zomer of alleen in de kerst worden getoond.
Dus bijvoorbeeld een flesje water die in de kerst en in de zomer verkocht kan worden, wordt niet getoond. Dus niet alle andere producten die of alleen in de zomer of alleen in de kerst worden getoond.
Gewijzigd op 18/12/2013 15:27:27 door Orlando Smits
Is het geen optie om voor elke checkbox die er is een query uit te voeren? Zou met behulp van een loopje vrij weinig code moeten zijn (over snelheid ga ik niet spreken)
Je hebt een database met drinken en wilt filteren op zomer en winter? Als het goed is moet dat prima werken. Heb je de laatste wijziging met AND OR gebruikt (Zie reactie Erwin)?
Laat anders wat relevante code zien.
Laat anders wat relevante code zien.
SELECT `product`.`product_id` , `product`.`naam` , `product`.`prijs` , `product`.`omschrijving` , `product`.`voorraad`
FROM `product` , `categorie` , `categorie_product`
WHERE `product` . `product_id` = `categorie_product`. `product_id`
AND `categorie`.`categorie_id` = `categorie_product`.`categorie_id`
AND `categorie`.`naam` = 'Zomer'
AND `categorie`.`naam` = 'Winter'
Tabellen:
Product (staan producten in)
Categorie (staan de categorieen in)
categorie_product (koppeltabel voor product en categorie)
FROM `product` , `categorie` , `categorie_product`
WHERE `product` . `product_id` = `categorie_product`. `product_id`
AND `categorie`.`categorie_id` = `categorie_product`.`categorie_id`
AND `categorie`.`naam` = 'Zomer'
AND `categorie`.`naam` = 'Winter'
Tabellen:
Product (staan producten in)
Categorie (staan de categorieen in)
categorie_product (koppeltabel voor product en categorie)
Orlando Smits op 18/12/2013 15:35:23:
SELECT `product`.`product_id` , `product`.`naam` , `product`.`prijs` , `product`.`omschrijving` , `product`.`voorraad`
FROM `product` , `categorie` , `categorie_product`
WHERE `product` . `product_id` = `categorie_product`. `product_id`
AND `categorie`.`categorie_id` = `categorie_product`.`categorie_id`
AND `categorie`.`naam` = 'Zomer'
AND `categorie`.`naam` = 'Winter'
Tabellen:
Product (staan producten in)
Categorie (staan de categorieën in)
categorie_product (koppeltabel voor product en categorie)
SELECT `product`.`product_id` , `product`.`naam` , `product`.`prijs` , `product`.`omschrijving` , `product`.`voorraad`
FROM `product` , `categorie` , `categorie_product`
WHERE `product` . `product_id` = `categorie_product`. `product_id`
AND `categorie`.`categorie_id` = `categorie_product`.`categorie_id`
AND `categorie`.`naam` = 'Zomer'
AND `categorie`.`naam` = 'Winter'
Tabellen:
Product (staan producten in)
Categorie (staan de categorieën in)
categorie_product (koppeltabel voor product en categorie)
Je hebt nu zomer AND winter, dus alle resultaten die in beide categorieën voorkomen.
Wil je dus ook producten die maar in 1 van de 2 categorieën voorkomt moet je de laatste wijzigen in OR.
WHERE `product` . `product_id` = `categorie_product`. `product_id`
AND `categorie`.`categorie_id` = `categorie_product`.`categorie_id`
AND `categorie`.`naam` = 'Zomer'
OR `categorie`.`naam` = 'Winter'
Edit:
Beter is denk ik nog om zomer en winter tussen haakjes te plaatsen
AND (`categorie`.`naam` = 'Zomer'
OR `categorie`.`naam` = 'Winter')
AND (`categorie`.`naam` = 'Zomer'
OR `categorie`.`naam` = 'Winter')
Gewijzigd op 18/12/2013 15:42:02 door Michael -
De vraag is hoe het opgeslagen wordt in database.
Dit lijkt mij een typisch voorbeeld van een meer op meer relatie, en dus zou er een linktabel moeten bestaan om de producten aan meerdere categorieën te kunnen koppelen.
Overigens is het een stuk eenvoudiger om WHERE ... IN te gebruiken dan elke keer ... = ... OR ... = ... te doen.
Dit lijkt mij een typisch voorbeeld van een meer op meer relatie, en dus zou er een linktabel moeten bestaan om de producten aan meerdere categorieën te kunnen koppelen.
Overigens is het een stuk eenvoudiger om WHERE ... IN te gebruiken dan elke keer ... = ... OR ... = ... te doen.
Zo te zien is er dus al normalisatie ten aanzien van de categorieen (heel goed overigens), dus dan wordt het een heel ander verhaal. Ten eerste moet je dan bepalen of een product dat aan 1 categorie voldoet moet worden gekozen, of alleen als het aan allen voldoet. Ten tweede zal je dan de rijen moeten gaan tellen.
Als je de having clause op 2 zet krijg je alleen de resultaten die aan alle categorieen voldoen, zet je het op >= 1 dan krijg je alle die 1 of meer hebben.
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
SELECT a.product_id, a.naam, a.prijs, a.omschrijving, a.voorraad
FROM product a
LEFT JOIN categorie_product b ON a.product_id = b.product_id
LEFT JOIN categorie c ON b.categorie_id = c.categorie_id
WHERE c.naam IN ('zomer', 'winter')
GROUP BY a.product_id, a.naam, a.prijs, a.omschrijving, a.voorraad
HAVING COUNT(*) = 2;
FROM product a
LEFT JOIN categorie_product b ON a.product_id = b.product_id
LEFT JOIN categorie c ON b.categorie_id = c.categorie_id
WHERE c.naam IN ('zomer', 'winter')
GROUP BY a.product_id, a.naam, a.prijs, a.omschrijving, a.voorraad
HAVING COUNT(*) = 2;
Als je de having clause op 2 zet krijg je alleen de resultaten die aan alle categorieen voldoen, zet je het op >= 1 dan krijg je alle die 1 of meer hebben.
Gewijzigd op 18/12/2013 15:58:06 door Erwin H
Als je ipv de categorie naam de id in de value van de checkbox kan je de categorie tabel buiten beschouwing laten.
Code (php)
1
2
3
4
5
6
2
3
4
5
6
<?php
$sql = "SELECT product_id, p.product_name, p.product_price
FROM product p
JOIN categorie_product c USING (product_id)
WHERE c.categorie_id IN (" . implode(',', $_POST['categorie'] . ')';
?>
$sql = "SELECT product_id, p.product_name, p.product_price
FROM product p
JOIN categorie_product c USING (product_id)
WHERE c.categorie_id IN (" . implode(',', $_POST['categorie'] . ')';
?>
Ger, merk wel op dat je zo resultaten dubbel kunt krijgen.
We hebben hem nu zo opgelost. Zo komen de producten tevoorschijn bij de categorieën.
SELECT `product`.`product_id` , `product`.`naam` , `product`.`prijs` , `product`.`omschrijving` , `product`.`voorraad`
FROM `product` , `categorie` , `categorie_product`
WHERE `categorie`.`naam` IN ('Zomer', 'winter')
AND `product` . `product_id` = `categorie_product`. `product_product_id`
AND`categorie`.`categorie_id` = `categorie_product`.`categorie_categorie_id`
GROUP BY naam
En natuurlijk iedereen bedankt voor de hulp!
SELECT `product`.`product_id` , `product`.`naam` , `product`.`prijs` , `product`.`omschrijving` , `product`.`voorraad`
FROM `product` , `categorie` , `categorie_product`
WHERE `categorie`.`naam` IN ('Zomer', 'winter')
AND `product` . `product_id` = `categorie_product`. `product_product_id`
AND`categorie`.`categorie_id` = `categorie_product`.`categorie_categorie_id`
GROUP BY naam
En natuurlijk iedereen bedankt voor de hulp!
Gewijzigd op 18/12/2013 16:00:05 door Orlando Smits
Idd Erwin, was de DISTINCT vergeten
@Orlando: Weet wel dat je een foute GROUP BY clause hebt. Als je docent een pietje precies is zal hij je daarop aanspreken. In een GROUP BY moeten in principe alle non-aggregate kolommen uit de select. In jouw geval dus allemaal.
Gewijzigd op 18/12/2013 16:02:23 door Erwin H
@Orlando,
Je gebruikt group_by zonder aggegrate functie, dus heb je hem niet nodig, en het maakt de query alleen maar trager.
Je gebruikt group_by zonder aggegrate functie, dus heb je hem niet nodig, en het maakt de query alleen maar trager.
Erwin H op 18/12/2013 16:01:54:
@Orlando: Weet wel dat je een foute GROUP BY clause hebt. Als je docent een pietje precies is zal hij je daarop aanspreken. In een GROUP BY moeten in principe alle non-aggregate kolommen uit de select. In jouw geval dus allemaal.
Oke dan hebben we hem aangepast, Bedankt!




