sql >> Database >  >> RDS >> Mysql

MySQL:voeg veel tabellen samen in één verklaring

Hoe krijg ik alle nakomelingen van een boomknooppunt met recursieve zoekopdracht in MySql?

Het is echt een probleem voor MySql, en het is een belangrijk punt voor deze vraag, maar je hebt nog steeds enkele keuzes.

Ervan uitgaande dat u over dergelijke voorbeeldgegevens beschikt, niet zoveel als uw steekproef, maar voldoende om aan te tonen:

create table treeNode(
id int, parent_id  int,  name varchar(10), type varchar(10),level int);
insert into treeNode 
(id, parent_id, name, type, level) values 
( 1,  0,  'C1    ', 'CATEGORY', 1),
( 2,  1,  'C1.1  ', 'CATEGORY', 2),
( 3,  2,  'C1.1.1', 'CATEGORY', 3),
( 4,  1,  'C1.2  ', 'CATEGORY', 2),
( 5,  4,  'C1.2.1', 'CATEGORY', 3),
( 3,  8,  'G1.1.1',    'GROUP', 3),
( 4,  9,  'G1.2  ',    'GROUP', 2),
( 5,  4,  'G1.2.1',    'GROUP', 3),
( 8,  9,  'G1.1  ',    'GROUP', 2),
( 9,  0,  'G1    ',    'GROUP', 1);

Eerste keuze:niveaucode

Zoals de voorbeeldgegevens van de naamkolom in de treeNode-tabel. (Ik weet niet hoe ik het in het Engels moet zeggen, geef commentaar op de juiste uitdrukking van level code .)

Om alle nakomelingen van C1 te krijgen of G1 zou zo simpel kunnen zijn:

select * from treeNode where type = 'CATEGORY' and name like 'C1%' ;
select * from treeNode where type = 'GROUP' and name like 'G1%' ;

Ik geef de voorkeur aan deze aanpak, we moeten zelfs deze code genereren voordat treeNode in de toepassing wordt opgeslagen. Het is efficiënter dan een recursieve query of procedure als we een groot aantal records hebben. Ik denk dat dit een goede denormalisatiebenadering is.

Met deze benadering, de verklaring je wilt met join zou kunnen zijn:

SELECT distinct p.* --if there is only one tree node for a product, distinct is not needed
FROM product p
JOIN product_type pt
     ON pt.id= p.parent_id -- to get product type of a product
JOIN linked_TreeNode LC
     ON LC.product_id= p.id -- to get tree_nodes related to a product
JOIN (select * from treeNode where type = 'CATEGORY' and name like 'C1%' ) C --may replace C1% to concat('$selected_cat_name','%')
     ON LC.treeNode_id = C.id
JOIN (select * from treeNode where type = 'GROUP' and name like 'G1%' ) G --may replace G1% to concat('$selected_group_name','%')
     ON LC.treeNode_id = G.id
WHERE pt.name = '$selected_type'  -- filter selected product type, assuming using product.name, if using product.parent_id, can save one join by pt like your original sql

Lief, nietwaar?

Tweede keuze:niveaunummer

Voeg een niveaukolom toe aan de treeNode-tabel, zoals weergegeven in de DDL.

Niveaunummer is veel gemakkelijker te onderhouden dan niveaucode in toepassing.

Met niveaunummer om alle nakomelingen van C1 te krijgen of G1 heb een klein trucje als dit nodig:

SELECT id, parent_id, name, type, @pv:=concat(@pv,',',id) as link_ids 
  FROM (select * from treeNode where type = 'CATEGORY' order by level) as t
  JOIN (select @pv:='1')tmp
 WHERE find_in_set(parent_id,@pv)
    OR find_in_set(id,@pv);
 -- get all descendants of `C1`

SELECT id, parent_id, name, type, @pv:=concat(@pv,',',id) as link_ids 
  FROM (select * from treeNode where type = 'GROUP' order by level) as t
  JOIN (select @pv:=',9,')tmp
 WHERE find_in_set(parent_id,@pv)
    OR find_in_set(id,@pv) ;

Deze benadering is langzamer dan de eerste, maar nog steeds sneller dan een recursieve zoekopdracht.

De volledige sql van de vraag is weggelaten. U hoeft alleen die twee subquery's van C en G te vervangen door twee bovenstaande query's.

Opmerking:

Er zijn veel vergelijkbare benaderingen, zoals hier , hier , of zelfs hier . Ze werken niet tenzij ze zijn besteld op niveaunummer of niveaucode. Je zou de laatste vraag kunnen testen in deze SqlFiddle door order by level te wijzigen om order by id om de verschillen te zien.

Nog een keuze:het geneste setmodel

Raadpleeg deze blog , heb ik nog niet getest. Maar ik denk dat het vergelijkbaar is met de laatste twee keuzes.

Je moet een linkernummer en een rechternummer aan de treenode-tabel toevoegen om alle afstammelingen-ID's tussen hen in te sluiten.



  1. exporteert imdbpy2sql.py soundtracks naar mysql?

  2. Genereer een unieke lange ID voor een weergave in MySql

  3. Node Mysql kan geen query in de wachtrij plaatsen na het aanroepen van quit

  4. SQL transponeren volledige tabel