sql >> Database teknologi >  >> RDS >> Mysql

Byg en dynamisk menu ved hjælp af indlejrede sæt

Følgende forespørgsel giver dig mulighed for at åbne enhver sti (eller sæt af stier) ved at drage fordel af SQL's have-klausul og MySQL's group_concat funktion.

Følgende er tabeldefinitionen og eksempeldata, jeg brugte:

slip tabel nested_set;CREATE TABLE nested_set (id INT, navn VARCHAR(20) NOT NULL, lft INT NOT NULL, rgt INT NOT NULL);INSERT INTO nested_set (id, navn, lft, rgt) VALUES ( 1,'HEAD',1,28);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (2,'A',2,3);INSERT INTO nested_set (id, navn, lft, rgt) VALUES ( 3,'B',4,17);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (4,'B1',5,10);INSERT INTO nested_set (id, navn, lft, rgt) VALUES ( 5,'B1.1',6,7);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (6,'B1.2',8,9);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (7,'B2',11,16);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (8,'B2.1',12,13);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (9,'B2.2',14,15);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (10,'C',18,25);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (11,'C1',19,20);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (12,'C2',21,22);INSERT INTO nested_set (id, navn, lft, rgt) VALUES (13,'C3',23,24);INSERT INT O indlejret_sæt (id, navn, lft, rgt) VALUES (14,'D',26,27); 

Følgende forespørgsel giver dig hele træet (undtagen HEAD):

SELECT node.id, node.lft, node.rgt, node.name, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS sti, (COUNT(parent.lft) - 1 ) AS depthFROM nested_set AS nodeinner join nested_set AS parenton node.lft MELLEM parent.lft OG parent.rgtwhere parent.lft> 1GROUP BY node.id 

Med et output på følgende, når det køres mod eksempeldataene:

+------+-----+-----+------+-------+----- --+| id | lft | rgt | navn | sti | dybde |+------+-----+-----+------+------------+------+| 2 | 2 | 3 | A | A | 0 || 3 | 4 | 17 | B | B | 0 || 4 | 5 | 10 | B1 | B/B1 | 1 || 5 | 6 | 7 | B1.1 | B/B1/B1.1 | 2 || 6 | 8 | 9 | B1.2 | B/B1/B1.2 | 2 || 7 | 11 | 16 | B2 | B/B2 | 1 || 8 | 12 | 13 | B2.1 | B/B2/B2.1 | 2 || 9 | 14 | 15 | B2.2 | B/B2/B2.2 | 2 || 10 | 18 | 25 | C | C | 0 || 11 | 19 | 20 | C1 | C/C1 | 1 || 12 | 21 | 22 | C2 | C/C2 | 1 || 13 | 23 | 24 | C3 | C/C3 | 1 || 14 | 26 | 27 | D | D | 0 |+------+-----+------+-----------------+-------+

Følgende tilføjelser til ovenstående forespørgsel vil give dig den kontrol, du skal bruge for at åbne de forskellige sektioner:

havingdepth =0or ('' =venstre(sti, længde('')) og dybde =længde('') - længde(erstat('' , '/', '')) + 1) 

Have-sætningen anvender filtre på resultaterne af gruppen efter forespørgsel. "Dybde =0"-delen er at sikre, at vi altid har basismenunoder (A, B, C og D). Den næste del er den del, der styrer hvilke noder der er åbne. Den sammenligner nodernes sti med en indstillet sti, du vil åbne ('') for at se, om den matcher, og den sørger også for, at den kun åbner niveau ind i stien. Hele eller sektionen med ''-logikken kan duplikeres og tilføjes efter behov for at åbne flere stier efter behov. Sørg for, at '' ikke ender med en efterfølgende skråstreg (/).

Følgende er nogle output-eksempler for at vise dig, hvordan du ville konstruere forespørgsler for at få de output, du ønskede:

=========Åbn B==========VÆLG node.id, node.lft, node.rgt, node.name, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS sti, (COUNT(parent.lft) - 1) AS depthFROM nested_set AS nodeinner join nested_set AS parenton node.lft MELLEM parent.lft OG parent.rgtwhere parent.lft> 1GROUP BY node. idhavingdepth =0 eller ('B' =venstre(sti, længde('B')) og dybde =længde('B') - længde(erstat('B', '/', '')) + 1)+- -----+-----+-----+------+------+------+| id | lft | rgt | navn | sti | dybde |+------+-----+-----+------+------+-------+| 2 | 2 | 3 | A | A | 0 || 3 | 4 | 17 | B | B | 0 || 4 | 5 | 10 | B1 | B/B1 | 1 || 7 | 11 | 16 | B2 | B/B2 | 1 || 10 | 18 | 25 | C | C | 0 || 14 | 26 | 27 | D | D | 0 |+------+-----+-----+------+------+-------+=========Åbn B og B/B1==========VÆLG node.id, node.lft, node.rgt, node.name, GROUP_CONCAT(forælder.navn ORDER BY parent.lft SEPARATOR "/" ) AS-sti, (COUNT(parent.lft) - 1) AS depthFROM nested_set AS nodeinner join nested_set AS parenton node.lft MELLEM parent.lft OG parent.rgtwhere parent.lft> 1GROUP BY node.idhavingdepth =0or ('B' =venstre(sti, længde('B')) og dybde =længde('B') - længde(erstat('B', '/', '')) + 1)eller ('B/B1' =venstre( sti, længde('B/B1')) og dybde =længde('B/B1') - længde(erstat('B/B1', '/', '')) + 1)+----- --+-----+-----+----------------------+| id | lft | rgt | navn | sti | dybde |+------+-----+-----+------+------------+------+| 2 | 2 | 3 | A | A | 0 || 3 | 4 | 17 | B | B | 0 || 4 | 5 | 10 | B1 | B/B1 | 1 || 5 | 6 | 7 | B1.1 | B/B1/B1.1 | 2 || 6 | 8 | 9 | B1.2 | B/B1/B1.2 | 2 || 7 | 11 | 16 | B2 | B/B2 | 1 || 10 | 18 | 25 | C | C | 0 || 14 | 26 | 27 | D | D | 0 |+------+-----+------+----------------+------+=========Åbn B og B/B1 og C==========VÆLG node.id, node.lft, node.rgt, node.name, GROUP_CONCAT(parent.name ORDER BY parent.lft SEPARATOR "/" ) AS sti, (COUNT(parent.lft) - 1) AS depthFROM nested_set AS nodeinner join nested_set AS parenton node.lft MELLEM parent.lft OG parent.rgtwhere parent.lft> 1GROUP BY node.idhavingdepth =0eller ('B' =venstre(sti, længde('B')) og dybde =længde('B') - længde(erstat('B', '/', '')) + 1)eller (' B/B1' =venstre(sti, længde('B/B1')) og dybde =længde('B/B1') - længde(erstat('B/B1', '/', '')) + 1 )eller ('C' =venstre(sti, længde('C')) og dybde =længde('C') - længde(erstat('C', '/', '')) + 1)+-- ----+-----+-----+----------------------+| id | lft | rgt | navn | sti | dybde |+------+-----+-----+------+------------+------+| 2 | 2 | 3 | A | A | 0 || 3 | 4 | 17 | B | B | 0 || 4 | 5 | 10 | B1 | B/B1 | 1 || 5 | 6 | 7 | B1.1 | B/B1/B1.1 | 2 || 6 | 8 | 9 | B1.2 | B/B1/B1.2 | 2 || 7 | 11 | 16 | B2 | B/B2 | 1 || 10 | 18 | 25 | C | C | 0 || 11 | 19 | 20 | C1 | C/C1 | 1 || 12 | 21 | 22 | C2 | C/C2 | 1 || 13 | 23 | 24 | C3 | C/C3 | 1 || 14 | 26 | 27 | D | D | 0 |+------+-----+------+-----------------+-------+ 

Det handler om det. du bliver ved med at duplikere den eller sektionen for hver sti, du skal åbne.

Se http://mikehillyer.com/articles/managing-hierarchical-data -in-mysql/ hvis du har brug for generel information om at arbejde med indlejrede sæt i MySQL.

Sig til, hvis du har spørgsmål.

HTH,

-Dipin



  1. skal jeg aktivere c3p0 statement pooling?

  2. Databasekontrolpunkter i SQL Server

  3. Den bedste måde at hoste MySQL på Azure Cloud

  4. Sådan opdateres indlejret JSON-datatype i MySQL 5.7