black Posted August 3, 2006 Report Share Posted August 3, 2006 Hello, Es nevaru izdomāt, ko lai iesāk ar kategoriju strukūru. Man ir interneta veikals, kurā ir n līmeņu kategorijas. Ir arī produkti, 1-N links uz kategoriju tabulu. Problēma ir uztaisīt kategoriju browseri, kas katrā kategorijā parādītu produktu skaitu, ieskaitot arī apakškategorijās esošos produktus. Rezultātam vajadzētu izskatīties šādi: Velosipēdi (20) Datori (12) Skaitlis iekavās nozīmē visu produktu skaiti apakškategorijās. Kādreiz taisīju to visu Oraclē un MaxDB, tur nebija problēmu uzrakstīt rekursīvu SQL kveriju, kas saskaita apakškategorijās esošos produktus, taču tagad es taisu projektu, kurā vienīgā datubāze ir MySQL 4.1. Tabulas (man, protams, ir vairāk lauku, bet piemēra pēc): categories( category_id int not null auto_increment, parent_id int, name varchar(50), primary key(category_id)); products( product_id int not null auto_increment, category_id int not null, name varchar(50), expires datetime, primary key(product_id)); Vai ir kādi ieteikumi, par to, kādu db struktūru izmantot? Es mēģināju katrai kategorijai pievienot size lauku, un pie katra produkta ievietošanas, palielinātu to par 1, bet produktiem ir noteikts derīguma termiņš, un size lauks kategorijā tāpēc, diemžēl, neder. Link to comment Share on other sites More sharing options...
koko Posted August 3, 2006 Report Share Posted August 3, 2006 (edited) SELECT a.*, COUNT(b.product_id) AS count FROM categories AS a LEFT JOIN products AS b ON (a.category_id=b.categoty_id) WHERE a.category_id = $mainiigais GROUP by a.id ORDER BY a.id; Apmēram šitā iekš MYSQL varētu strādāt, ja runa iet par mysql (es, protams, varu arī kļūdīties) Edited August 3, 2006 by koko Link to comment Share on other sites More sharing options...
cucumber Posted August 3, 2006 Report Share Posted August 3, 2006 caur ko taisi, labak katrai kategorijai savs id, bet precem savs id, kaut vai viena table visu met Link to comment Share on other sites More sharing options...
bubu Posted August 3, 2006 Report Share Posted August 3, 2006 cucumber: vienā tabulā noteitki nevajag mest. Vēlāk tikai problēmas ar kverīšiem būs. Un paskaties uz viņa tabulu definīciju - viņam jau tur ir tieši to ko saki - katram savs id. koko jau vispār atbildēja uz autora jautājumu. Link to comment Share on other sites More sharing options...
black Posted August 3, 2006 Author Report Share Posted August 3, 2006 (edited) Koko paldies par kveriju. Tā problēma ir, ka viņš neatbalsta n-līmeņu kategorijas - šis varētu strādāt, ja kategorijas būtu tikai 1-2 līmeņos. Ti, tagad viņš atgrieztu produktu skaitu zemākā līmeņa kategorijās, bet man vajag listu, kas satur augstākā līmeņa kategorijas. Cucumber domu īsti nesapratu. Edited August 3, 2006 by black Link to comment Share on other sites More sharing options...
koko Posted August 3, 2006 Report Share Posted August 3, 2006 black, strādā gan daudzos līmeņos... Tam jau domāta kategorijas id, jo kategorijai jau ir parent id... Līdz ar to ir pofig, cik līmeņos... Pašas kategorijas izvadi pēc algoritma, kas apstrādā pēc parent_id, un tad jau mans kverijs... Tur pat nav daudz ko domāt - paskaties uz struktūru :) Link to comment Share on other sites More sharing options...
black Posted August 3, 2006 Author Report Share Posted August 3, 2006 Joprojām īsti nesapratu - tu tā kverija rezultātu iesaki pēc tam ar PHP vēlreiz sagrupēt? Tas īsti neder, jo kategorijas ir pārdesmit tūkstoši. Link to comment Share on other sites More sharing options...
bubu Posted August 3, 2006 Report Share Posted August 3, 2006 Ja kategorijas nevajadzēs bieži pārvietot (dārga operācija), tad paskaties uz nested set modeli: http://dev.mysql.com/tech-resources/articl...hical-data.html Tev vajadzīgais kverīts ir pie: "Aggregate Functions in a Nested Set" Link to comment Share on other sites More sharing options...
black Posted August 3, 2006 Author Report Share Posted August 3, 2006 Nested setam gadījumā nebija jāmaina apmēram puse no kategorijām pie inserta? Tad pie katra kategorijas inserta 10K updeiti... Brr... Link to comment Share on other sites More sharing options...
Delfins Posted August 3, 2006 Report Share Posted August 3, 2006 (edited) Nu vispār var jau taisīt cached-variantu... tobiš... - pie preču pievienošanas pārskaita skaitu un pieraksta skaitu klāt kategorijai... vēlāk vnk selektējot nemaz nevajag neko joinot/skaitīt. - ja notiek preču multi-inserti (vairākas preces), palaist pārskaitīšanas jobu uz visām affected-kategorijam... Kas jāzidara: jāuzraksta rekursīvā f-ja, kas skaita un updeito kategoriju sākot no apakšas (storētā vai PHP) Risinājums ir šāds: 1.) SELECT kat_id, count(prece_id) FROM preces GROUP BY kat_id * tāpēc, ka lai neveidotu N-query uz katru kategoriju, ja būs rekursīvs updeits 2.) FOREACH kat_id DO update_kategorija(kat_id,preces_cnt) 3.) rekursīvs updeits kategorijām kuram ir N-childi (tiks skaitiits kopaa tikai kategoriju lauks precu_skaits) * 1. un 2. var būt iekš vienas procedūras Edited August 3, 2006 by Delfins Link to comment Share on other sites More sharing options...
black Posted August 3, 2006 Author Report Share Posted August 3, 2006 Shito jau biju iedomaajies, tachu ir viena probleema - produktu expire_date. Tas nozīmē, ka pieejamo produktu skaits mainās atkarībā no pašreizējā datuma. :( Link to comment Share on other sites More sharing options...
Delfins Posted August 3, 2006 Report Share Posted August 3, 2006 cron-jobs: recursive_count_update_down(0); // update from root to leafs Link to comment Share on other sites More sharing options...
black Posted August 3, 2006 Author Report Share Posted August 3, 2006 Tā arī nāksies darīt, lai gan gribētos, protams, lai varētu kaut kā uztaisīt bez cronjoba... Link to comment Share on other sites More sharing options...
Delfins Posted August 4, 2006 Report Share Posted August 4, 2006 tici man, cronjobs atmaksāsies 100x, nekā tu katram pieprasījumam rekursīvi kaut ko skaitīsi... es jau nerunāju par botiem, kuri vienkārši uzkarinās tev serveri... Link to comment Share on other sites More sharing options...
Recommended Posts