Tuesday, March 19, 2013

SQL da GROUP BY dan to`g`ri foydalanish

Assalomu alaykum. Quyida 2 usul keltirilgan, Odatdada ancha kuchli programmistlar ham 1-usulni bilishadi va shundan foydalanishadi. Ammo bundan yaxshirog`i ham bor, 2- usul. hozir solishtiramiz.


/*create table computers
as 
select 1 id, 'Bekorchi' "name"
union all
select 2, 'Mikrob'
union all
select 3, 'Virus';

create table userNames
as
select 1 id, 1 computersid,'Unknown' userName
union all
select 2, 1,'Noname'
union all
select 3, 1,'Benom'
union all
select 4, 2,'Bebaho'
union all
select 5, 2,'Arzon'
union all
select 6, 3,'Ismi yo`q';
*/
-- 1-usul
select id, name, (select count(id) from usernames where computersid=c.id) usersCount 
from computers c
order by name;

-- 2-usul
select c.id, max(c.name) "name", count(u.id) usersCount 
from computers c 
left join userNames u on c.id=u.computersid
group by c.id
order by max(c.name);

---------------------------------------------------------------------

Demak, 1- usulni tahlil qilsak:
computers tablitsasidan nechta qator chiqarish kerak bo`lsa SELECT shuncha marta takrorlanadi. Masalan: 1000 ta qator chiqarilishi kerak bo`lsa userNames tablitsasi 1000 marta SELECT  qilinadi.
2- usulda esa. JOIN dan foydalandim. GROUP BY qo`rqinchli narsa emas - agar undan to`g`ri foydalanilsa -ya`ni bu narsa queeryni sekinlalshtirish uchun chiqarilmagan :-). 
JOIN dan foydalanganimizni asosiy sababi - 2 ta tablitsa bir biriga indexlanadi va join bo`ladi. bu nihoyatda tez bo`ladi. agarda row lar soni ko`p bo`lsa yaqqol bilinadi. Gruppirovkani Integer polya bo`yicha qilganimiz uchun juda kam vaqt sarflanadi. bu yerda max lar uchun deyarli vaqt ketmaydi(pastda tushintirilgan).

Shu o`rinda GROUP BY haqida ma`lumot berib o`tmoqchimiz. Agarda c.id bo`yicha gruppirovka qilinsa, demak bizga c.name bo`yicha yoki computers tablitsasining biror boshqa columni  bo`yicha gruppirovka qilishimizni keragi yo`q. Chunki 1 ta c.id gruppirovka qilinsa yetarli- ya`ni 1 ta c.id ga bitta qator ya`ni bitta row(zapis) to`g`ri keladi. 
Yanada soddaroq tushuntiramiz-  nima uchun max degan aggregate funksiyadan foydalandik, o`rniga min qo`ysak bo`lmasmikan?  Bo`ladi. Nega? Asosiy narsa ham shunda! Chunki c.id bilan gruppirovka qilinganda o`zi har bir c.id ga bittadan c.name to`g`ri kelib qolgandiku, demak max(c.name)=min(c.name), agar bu qator varchar emas integer bo`lsa sum ni ham foydalansa xato bo`lmaydi. Ya`ni 1 ta sonni maximum, minimum, sum lari bir xil!(bu yerda max lar uchun deyarli vaqt ketmaydi)

Agar max, min qo`ymasak bo`lmaydi. quyidagi xatolik chiqadi:
ERROR:  column "c.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 28: select c.id, c.name "name", count(u.id) usersCount 
Odatda bu xatolikni ko`rgan dasturchi darhol c.name ni GROUP BY ga qo`shib qo`yar ekan. Bu katta logic xato!

No comments:

Post a Comment