GROUP_CONCAT om dropdown te verkrijgen
Ik wil graag verschillende drop downs kunnen genereren, zoals voorbeeld,
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<label>optie a</label>
<select>
<option>40</option>
<option>50</option>
</select>
.......
<label>optie b</label>
<select>
<option>60</option>
<option>70</option>
</select>
<select>
<option>40</option>
<option>50</option>
</select>
.......
<label>optie b</label>
<select>
<option>60</option>
<option>70</option>
</select>
Mijn Query ziet er als volgt uit:
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
29
30
31
32
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
29
30
31
32
SELECT
p.product_id,
GROUP_CONCAT( DISTINCT CONCAT( optlan.option_label,',',ovl.value) SEPARATOR ';') AS options_01,
CONCAT(GROUP_CONCAT(DISTINCT optlan.option_label),';', GROUP_CONCAT(DISTINCT ovl.value)) AS options_02,
CONCAT_WS(';', optlan.option_label, GROUP_CONCAT(DISTINCT ovl.value) ) AS options_03
FROM
products p
JOIN category c
ON p.category_id = c.category_id
LEFT JOIN
options_categories opcat
ON opcat.category_id = c.category_id
LEFT JOIN
options opt
ON opt.option_id = opcat.option_id
LEFT JOIN
options_lang optlan
ON optlan.option_id = opt.option_id AND optlan.lang_id = 'NL'
LEFT JOIN
option_values ov
ON ov.option_id = opt.option_id
LEFT JOIN
option_values_lang ovl
ON ovl.value_id = ov.value_id AND ovl.lang_id = 'NL'
WHERE p.product_id = '25'
GROUP BY p.product_id
p.product_id,
GROUP_CONCAT( DISTINCT CONCAT( optlan.option_label,',',ovl.value) SEPARATOR ';') AS options_01,
CONCAT(GROUP_CONCAT(DISTINCT optlan.option_label),';', GROUP_CONCAT(DISTINCT ovl.value)) AS options_02,
CONCAT_WS(';', optlan.option_label, GROUP_CONCAT(DISTINCT ovl.value) ) AS options_03
FROM
products p
JOIN category c
ON p.category_id = c.category_id
LEFT JOIN
options_categories opcat
ON opcat.category_id = c.category_id
LEFT JOIN
options opt
ON opt.option_id = opcat.option_id
LEFT JOIN
options_lang optlan
ON optlan.option_id = opt.option_id AND optlan.lang_id = 'NL'
LEFT JOIN
option_values ov
ON ov.option_id = opt.option_id
LEFT JOIN
option_values_lang ovl
ON ovl.value_id = ov.value_id AND ovl.lang_id = 'NL'
WHERE p.product_id = '25'
GROUP BY p.product_id
options_01 geeft:
optie a,40;optie a,50;optie b,60;optie b,70
options_2 geeft:
optie a,optie b;40,50,60,70
en options_03:
optie b;60,70
Hetgeen ik zou willen is dit, maar ja.....
optie a;40,50|optie b;60,70
Stel ik heb 2 tabellen
Tabel 1: options => option_id and option_label Tabel 2: values => value_id, option_id and value
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
CREATE TABLE `options` (
`option_id` int(5) UNSIGNED NOT NULL,
`option_label` varchar(100) NOT NULL DEFAULT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;
CREATE TABLE `values` (
`value_id` int(5) UNSIGNED NOT NULL,
`option_id` int(5) UNSIGNED NOT NULL ,
`value` varchar(100) NOT NULL DEFAULT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
`option_id` int(5) UNSIGNED NOT NULL,
`option_label` varchar(100) NOT NULL DEFAULT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;
CREATE TABLE `values` (
`value_id` int(5) UNSIGNED NOT NULL,
`option_id` int(5) UNSIGNED NOT NULL ,
`value` varchar(100) NOT NULL DEFAULT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
en deze worden gevuld met:
Code (php)
1
2
3
2
3
INSERT INTO options (option_id, option_label) VALUES (1, 'option a'), (2, 'option b');
INSERT INTO values (value_id, option_id, value) VALUES (1, 1, 'val 1a'), (2, 1, 'val 2a'), (3, 1, 'val 3a'), (4, 2, 'val 1b'), (5, 2, 'val 2b'),;
INSERT INTO values (value_id, option_id, value) VALUES (1, 1, 'val 1a'), (2, 1, 'val 2a'), (3, 1, 'val 3a'), (4, 2, 'val 1b'), (5, 2, 'val 2b'),;
De query ziet er dan als volgt uit, alleen wat ik op de puntjes moet invullen is de grote vraag....
Code (php)
1
2
3
4
5
6
2
3
4
5
6
SELECT
GROUP_CONCAT ........... AS all_options
FROM options o
JOIN values v
ON o.option_id = v.option_id
GROUP BY o.option_id
GROUP_CONCAT ........... AS all_options
FROM options o
JOIN values v
ON o.option_id = v.option_id
GROUP BY o.option_id
De uitkomst van de query:
all_options "option a;val 1a,val 2a,val 3a|option b;val 1b,val 2b"
Misschien is het makkelijker om de tweede (zijn er nog meer? of is dit altijd maar 1 niveau diep?) dropdown op afroep te vullen, bijvoorbeeld via AJAX. Wanneer je een waarde selecteert in dropdown X stuur je een GET of POST request naar je applicatie met de geselecteerde waarde. Deze retourneert vervolgens JSON-data waarmee je via JavaScript een tweede (of volgende) dropdown genereert.
Dit is onderdeel van een PIM. Er moeten opties aan een product worden toegevoegd om in de webshop wel of niet getoond te worden.
Ik heb de oplossing "god zij dank" of is het zei ? ;-).
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
29
30
31
32
33
34
35
36
37
38
39
40
41
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
29
30
31
32
33
34
35
36
37
38
39
40
41
SELECT
p.product_id,
c.category_id,
cl.lang_value,
IFNULL(GROUP_CONCAT(DISTINCT options SEPARATOR '_'), NULL) AS options
FROM
products p
JOIN
category c
ON p.category_id = c.category_id
LEFT JOIN
category_lang cl
ON c.category_id = cl.category_id AND lang_id = 'NL'
LEFT JOIN
(SELECT
opcat.category_id,
CONCAT_WS(';', optlan.option_label, GROUP_CONCAT(DISTINCT ovl.key,'|',ovl.value ORDER BY ovl.value) ) AS options
FROM
options_categories opcat
INNER JOIN
options opt
ON opt.option_id = opcat.option_id
INNER JOIN
options_lang optlan
ON optlan.option_id = opt.option_id
INNER JOIN
option_values ov
ON ov.option_id = opt.option_id
INNER JOIN
option_values_lang ovl
ON ovl.value_id = ov.value_id
WHERE optlan.lang_id = 'NL' AND ovl.lang_id = 'NL'
GROUP BY optlan.option_label ) t
ON t.category_id = c.category_id
WHERE p.display =1
GROUP BY p.product_id
p.product_id,
c.category_id,
cl.lang_value,
IFNULL(GROUP_CONCAT(DISTINCT options SEPARATOR '_'), NULL) AS options
FROM
products p
JOIN
category c
ON p.category_id = c.category_id
LEFT JOIN
category_lang cl
ON c.category_id = cl.category_id AND lang_id = 'NL'
LEFT JOIN
(SELECT
opcat.category_id,
CONCAT_WS(';', optlan.option_label, GROUP_CONCAT(DISTINCT ovl.key,'|',ovl.value ORDER BY ovl.value) ) AS options
FROM
options_categories opcat
INNER JOIN
options opt
ON opt.option_id = opcat.option_id
INNER JOIN
options_lang optlan
ON optlan.option_id = opt.option_id
INNER JOIN
option_values ov
ON ov.option_id = opt.option_id
INNER JOIN
option_values_lang ovl
ON ovl.value_id = ov.value_id
WHERE optlan.lang_id = 'NL' AND ovl.lang_id = 'NL'
GROUP BY optlan.option_label ) t
ON t.category_id = c.category_id
WHERE p.display =1
GROUP BY p.product_id
Ik hoop hier alleen dat je niet afhankelijk bent van het gedrag van de foute GROUP BY. Anders zul je nog wat dingen moeten omgooien: in GROUP BY *moeten* alle velden genoemd worden die geen aggregate zijn.
De uiteindelijke query is nog langer en werkt goed.
Helaas begrijp ik niet goed wat je bedoeld maar wil dit wel graag weten, want fout = fout.
Kun je aangeven in een voorbeeld wat je bedoeld ?
Dank je wel alvast
Toevoeging op 24/06/2017 10:48:56:
Zag inderdaad een fout , nu:
Gewijzigd op 24/06/2017 11:54:26 door Ben van Velzen
Hoe voeg je ONLY_FULL_GROUP_BY toe aan sql_mode ?
Door een query te draaien in de vorm van SET sql_mode = ... of de serverconfiguratie aan de passen.