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

Hvilken hierarkisk model skal jeg bruge? Tilgrænsende, indlejret eller opregnet?

Typisk er der tre slags forespørgsler i hierarkierne, som forårsager problemer:

  1. Tilbagefør alle forfædre
  2. Returner alle efterkommere
  3. Returner alle børn (umiddelbare efterkommere).

Her er en lille tabel, som viser ydelsen af ​​forskellige metoder i MySQL :

                        Ancestors  Descendants  Children        Maintainability InnoDB
Adjacency list          Good       Decent       Excellent       Easy            Yes
Nested sets (classic)   Poor       Excellent    Poor/Excellent  Very hard       Yes
Nested sets (spatial)   Excellent  Very good    Poor/Excellent  Very hard       No
Materialized path       Excellent  Very good    Poor/Excellent  Hard            Yes
 

I children , poor/excellent betyder, at svaret afhænger af, om du blander metoden med adjacency list, dvs. e. lagring af parentID i hver post.

Til din opgave har du brug for alle tre forespørgsler:

  1. Alle forfædre skal vise Jorden / Storbritannien / Devon tingen
  2. Alle børn skal vise "Destinationer i Europa" (genstandene)
  3. Alle efterkommere skal vise "Destinationer i Europa" (tæller)

Jeg ville gå efter materialiserede veje, da denne form for hierarki sjældent ændrer sig (kun i tilfælde af krig, oprør osv.).

Opret en varchar-kolonne kaldet path , indekser det og udfyld det med værdien som denne:

1:234:6345:45454:
 

hvor tallene er primærnøgler for de relevante forældre, i korrekt rækkefølge (1 for Europa, 234 for Storbritannien osv.)

Du skal også bruge en tabel kaldet levels for at beholde numre fra 1 til 20 (eller hvilket maksimalt indlejringsniveau du ønsker).

Sådan vælger du alle forfædre:

SELECT pa.* FROM places p JOIN levels l ON SUBSTRING_INDEX(p.path, ':', l.level) <> p.path JOIN places pa ON pa.path = CONCAT(SUBSTRING_INDEX(p.path, ':', l.level), ':') WHERE p.id = @id_of_place_in_devon

Sådan vælger du alle børn og antal steder inden for dem:

SELECT  pc.*, COUNT(pp.id)
FROM    places p
JOIN    places pc
ON      pc.parentId = p.id
JOIN    places pp
ON      pp.path BETWEEN pc.path AND CONCAT(pc.path, ':')
        AND pp.id NOT IN
        (
        SELECT  parentId
        FROM    places
        )
WHERE   p.id = @id_of_europe
GROUP BY
        pc.id
 


  1. 2 måder at konvertere et tal til oktal i MySQL

  2. Hvad er nyt i PostgreSQL 12

  3. Kan ikke finde en input type=image værdi i $_POST

  4. Henvisning til et kolonnealias i en WHERE-klausul