shurix Posted June 30, 2011 Report Share Posted June 30, 2011 Taisu komentēšanu lapai un netieku skaidrībā, kādu query man vajag, lai izvadītu komentārus. Ir 3 tabulas komentari - visi komentāri, komentari_atb - atbildes uz komentāriem, users - useru dati. Es gribu izvadīt komentāru un tad aiz viņa visas atbildes un atkal nākošo komentāru ar visām viņa atbildēm + gan komentāram gan atbildei paņemt no users vārdu un bildīti. Pats uzmeisteroju kaut ko šādu, bet protams īsti tur nenotiek tas ko vajadzētu. SELECT komentari.*, komentari_atb.*, users.* from komentari left outer join komentari_atb on komentari.id=komentari_atb.kid left outer join users on komentari.user_id=users.user_id or komentari_atb.user_id=users.user_id Quote Link to comment Share on other sites More sharing options...
daGrevis Posted June 30, 2011 Report Share Posted June 30, 2011 Dari tā, ka ir divas tabulas: comments un users. Comments tabulai uztaisi lauku reply_id (vai kā tā)... kurš būs 0, ja šis komentārs nav atbilde kādam citam komentāram. Ja šis komentārs ir atbilde komentāram (ironija), tad reply_id saturēs galvenā komentāra id. P.S. Un pieprasījumu Es tā "uz sitienu" nemāku uzrakstīt. Quote Link to comment Share on other sites More sharing options...
shurix Posted June 30, 2011 Author Report Share Posted June 30, 2011 Tādu variantu es arī biju iedomājies, bet izdomāju, ka querijam, lai dabūtu atbildes ir jāiet cauri arī pašiem komentāriem, kas it kā ir lieki un patērē laiku. Atbildes atsevišķi būs mazāk un ātrāk, vismaz pēc manas loģikas :D Quote Link to comment Share on other sites More sharing options...
Roberts.R Posted July 1, 2011 Report Share Posted July 1, 2011 (edited) Tādu variantu es arī biju iedomājies, bet izdomāju, ka querijam, lai dabūtu atbildes ir jāiet cauri arī pašiem komentāriem, kas it kā ir lieki un patērē laiku. Atbildes atsevišķi būs mazāk un ātrāk, vismaz pēc manas loģikas :D Nu ja Tev ļoti švaka kaste, tad jā, bet pa lielam, tāds CMS kā Wordpress tikai uz tādu principu strādā, kā minēja dagrevis. Tie saucās Parent'i. Nu vismaz es tā tos saucu. Pats arī bieži praktizēju, un viss iet kā nākas. šitas diezgan vecs paraugs, ko pats izmantoju vienā lapā: $query = "SELECT c.id, c.poster, c.content, c.time, u.id as u_id, u.img FROM content c INNER JOIN users u WHERE u.id = c.author AND c.type='discussion' AND c.parent_id = (SELECT id FROM content WHERE id = '".$discussion_id."')"; Kokains gan jau ir, bet izlobīt ideju var ;) Edited July 1, 2011 by Roberts.R Quote Link to comment Share on other sites More sharing options...
Grey_Wolf Posted July 1, 2011 Report Share Posted July 1, 2011 (edited) Atbildes atsevišķi būs mazāk un ātrāk, vismaz pēc manas loģikas :D Nē nebūs ne ātrāk, ne ekonomiskāk. Jo šaurā vieta ir datu pārsūtīšana no SQL uz PHP , un kveriju sākotnējā apstrāde. piedevām SQL ļoti labi māk nokešot pieprasījumus, bet ne bezgalīgi daudz, ja nenāks klāt neviens komentārs , tad nākamajā reizē pieprasījums tiks ņemts no keša - attiecīgi apstrādes laiks krietni saruks edit: varu pateikt arī kāpēc glabāt atbildes uz komentāriem atsevīšķā tabulā ir slikti. iedomājies situāciju ka kāds komentārs jaizdzēš. No kuras tabulas tu viņu ņemsi ? Nāksies pārsūtīt 2 datus: ID un kurai tabulai pieder ( pamat komentiem, vai atbildēm) turpretīm ja būs viena tabula tad pietiks ar ID, samērā primitīvs PHP kods .. 1 forma (ja vajag pielabot[cenzēt]) + datu apstrāde šai formai.. Edited July 1, 2011 by Grey_Wolf Quote Link to comment Share on other sites More sharing options...
daGrevis Posted July 1, 2011 Report Share Posted July 1, 2011 SELECT `content` FROM `posts` WHERE `reply_id` = '3' Pat "join'u" nevajadzēja! Quote Link to comment Share on other sites More sharing options...
Gints Plivna Posted July 1, 2011 Report Share Posted July 1, 2011 Tas vienas tabulas piegājiens arī būs mazliet universālāks tādā veidā, ka teorētiski tajā var glabāt n līmeņus nevis tikai 2. Tiesa gan MySQL piemēram ir lielas problēmas ar šādu rekursīvu vaicājumu veidošanu, bet nu varbūt kādreiz kāds kaut ko darīs šai lietā. Vēl dažas piebilde pie iepriekšējā: - komentāru tabulai tā kā acīmredzit vajadzētu būt saitei uz kaut kādiem rakstiem vai whatever, kas nu tas ir kam tie komentāri pievienoti - lai nebūtu viss jālasa, tad atceramies, ka esksistē taču tāda lieta kā indeksi. Anyway viens no piemēriem varētu izskatīties šādi: Ir tabula komentāri - man tai trūkst kolonas uz lietotāju, bet nu to vari pats izveidot. Un daži ieraksti. mysql> create table comments (com_id int not null auto_increment primary key, -> com_art_id int not null, -> com_com_id int, -> com_text varchar(100)); Query OK, 0 rows affected (0.78 sec) mysql> insert into comments values (1, 1, null, 'pirmais kom'), -> (2, 1, 1, 'atb uz pirmo kom'), -> (3, 1, null, 'otrais kom'), -> (4, 1, null, 'treshais kom'), -> (5, 1, 1, 'otra atb uz pirmo kom'), -> (6, 1, 4, 'atb uz tresho kom'), -> (7, 1, 4, 'otra atb uz tresho kom'); Query OK, 7 rows affected (0.03 sec) Records: 7 Duplicates: 0 Warnings: 0 Rezultātu iegūst šādi: mysql> SELECT com_id, com_com_id, 1 as level, com_text -> FROM comments -> WHERE com_art_id = 1 -> AND com_com_id is null -> UNION ALL -> SELECT c2.com_id, c2.com_com_id, 2 as level, c2.com_text -> FROM comments c1 -> INNER JOIN comments c2 -> ON (c1.com_id = c2.com_com_id) -> WHERE c1.com_art_id = 1 -> AND c1.com_com_id is null -> ORDER BY coalesce(com_com_id, com_id), com_id; +--------+------------+-------+------------------------+ | com_id | com_com_id | level | com_text | +--------+------------+-------+------------------------+ | 1 | NULL | 1 | pirmais kom | | 2 | 1 | 2 | atb uz pirmo kom | | 5 | 1 | 2 | otra atb uz pirmo kom | | 3 | NULL | 1 | otrais kom | | 4 | NULL | 1 | treshais kom | | 6 | 4 | 2 | atb uz tresho kom | | 7 | 4 | 2 | otra atb uz tresho kom | +--------+------------+-------+------------------------+ 7 rows in set (0.00 sec) Tagad veidojam indeksus: mysql> create index com_idx1 on comments(com_art_id, com_com_id); Query OK, 0 rows affected (0.23 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> create index com_idx2 on comments(com_com_id); Query OK, 0 rows affected (0.19 sec) Records: 0 Duplicates: 0 Warnings: 0 Un skatamies kā tad vaicājums izskatīsies: mysql> explain -> SELECT com_id, com_com_id, 1 as level, com_text -> FROM comments -> WHERE com_art_id = 1 -> AND com_com_id is null -> UNION ALL -> SELECT c2.com_id, c2.com_com_id, 2 as level, c2.com_text -> FROM comments c1 -> INNER JOIN comments c2 -> ON (c1.com_id = c2.com_com_id) -> WHERE c1.com_art_id = 1 -> AND c1.com_com_id is null -> ORDER BY coalesce(com_com_id, com_id), com_id; +----+--------------+------------+------+---------------------------+----------+---------+----------------+------+-------------------------- + | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------+------------+------+---------------------------+----------+---------+----------------+------+-------------------------- + | 1 | PRIMARY | comments | ref | com_idx1,com_idx2 | com_idx1 | 9 | const,const | 3 | Using where | | 2 | UNION | c1 | ref | PRIMARY,com_idx1,com_idx2 | com_idx1 | 9 | const,const | 3 | Using where; Using index | | 2 | UNION | c2 | ref | com_idx2 | com_idx2 | 5 | test.c1.com_id | 1 | Using where | | NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | Using filesort | +----+--------------+------------+------+---------------------------+----------+---------+----------------+------+-------------------------- + 4 rows in set (0.00 sec) Principā var redzēt, ka nekur full skans (ALL iekš type) tabulām nav. Tas ir tikai rezultātu apvienošanai, no kuras īsti izbēgt šķiet nevar. It kā jau sanāk, ka tos pirmā līmeņa komentārus lasa 2reiz, jo otrreiz tos vajag tikai priekš otrā līmeņa komentāru atrašanas un pēc tam met ārā, bet nu, ja raksta vienkārši left join, tad tie sanāk vienā rindā kopā ar otrā līmeņa komentāriem un tad tos jāķeksē ārā kaut kā programmatoriski. Reālā dzīvē arī tur varētu parādīties vairāki using index, jo šobrīd datu daudzums ir tik mazs (tikai priekš 1 raksta), ka tas īsti neatspoguļo iespējamo realitāti. Gints Plivna http://datubazes.wordpress.com Quote Link to comment Share on other sites More sharing options...
codez Posted July 1, 2011 Report Share Posted July 1, 2011 (edited) Jautājums Gintam - Vai tad tavā tabulas struktūras variantā, komentārus nevar atlasīt vienkārši šādi: SELECT * FROM comments WHERE com_art_id=1 ORDER BY coalesce(com_com_id,com_id),com_id ? Edited July 1, 2011 by codez Quote Link to comment Share on other sites More sharing options...
Gints Plivna Posted July 1, 2011 Report Share Posted July 1, 2011 Jautājums Gintam - Vai tad tavā tabulas struktūras variantā, komentārus nevar atlasīt vienkārši šādi: SELECT * FROM comments WHERE com_art_id=1 ORDER BY coalesce(com_com_id,com_id),com_id ? Viss ģeniālais ir vienkāršs :) Tev taisnība. mysql> select com_id, case when com_com_id is NULL then 1 else 2 end as level, com_text -> FROM comments WHERE com_art_id=1 ORDER BY coalesce(com_com_id,com_id),com_id; +--------+-------+------------------------+ | com_id | level | com_text | +--------+-------+------------------------+ | 1 | 1 | pirmais kom | | 2 | 2 | atb uz pirmo kom | | 5 | 2 | otra atb uz pirmo kom | | 3 | 1 | otrais kom | | 4 | 1 | treshais kom | | 6 | 2 | atb uz tresho kom | | 7 | 2 | otra atb uz tresho kom | +--------+-------+------------------------+ 7 rows in set (0.00 sec) Diviem līmeņiem var tiešām šādi. Trīs jau laikam tomēr vairs nevarētu :) Un līdz ar to visādi tur ātrdarbības satraukumi arī izgaist pavisam. Gints Plivna http://datubazes.wordpress.com Quote Link to comment Share on other sites More sharing options...
Rincewind Posted July 1, 2011 Report Share Posted July 1, 2011 (edited) Kaut ko līdzīgu esmu taisījis. Domu gājiens bija tāds ka ātrdarbība pie komentāra ievietošanas nav tik svarīga kā pie nolasīšanas. Strādā ar neierobežotiem līmeņiem. Detaļās īpaši neiedziļināšos, aprakstīšu vispārīgi. Tabula: id topic_id comment level display_order Piemērs: 1 1 Komentārs_1 0 1 2 1 Atbilde_1_1 1 2 3 1 Atbilde_1_2 1 3 4 1 Atbilde_1_2_1 2 4 5 1 Komentārs_2 0 5 6 1 Komentārs_3 0 6 7 1 Atbilde_3_1 1 7 Ja atbilde uz topiku tad pie inserta level = 0 un display_order = MAX(display_order topikam)+1 Ja atbilde uz komentu tad: Skatamies komentāra uz kuru atbild id un iegūstam viņa level un display_order UPDATE tabula SET display_order = display_order+1 WHERE display_order>$display_order AND topic_id=$topic_id INSERT .... level=$level+1 ... display_order = komentāra display_order + 1 ... Atbilstoši selekts ir: SELECT FROM tabula WHERE topic_id=$topic ORDER BY display_order LIMIT cik nu vajag Īsumā tā. Trūkums tāds ka nevar selektu limitēt pēc augšējā līmeņa komentāriem. Vai var? Edited July 1, 2011 by Rincewind Quote Link to comment Share on other sites More sharing options...
shurix Posted July 3, 2011 Author Report Share Posted July 3, 2011 Paldies par atbildēm, izdevās arī pievienot useru tabulu un viss gandrīz ir labi. Izņemot to, ka nemāku uzlikt limitu, lai ņemtu vērā tikai level 1 komentāru. 10 galvenie komentāri lapā, bet neierobežots skaits atbilžu. Quote Link to comment Share on other sites More sharing options...
shurix Posted July 4, 2011 Author Report Share Posted July 4, 2011 Paldies par atbildēm, izdevās arī pievienot useru tabulu un viss gandrīz ir labi. Izņemot to, ka nemāku uzlikt limitu, lai ņemtu vērā tikai level 1 komentāru. 10 galvenie komentāri lapā, bet neierobežots skaits atbilžu. anyone? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.