Əsas səhifə > MySQL, Oracle, Oracle SQL > MySQL’s Group by vs. Oracle’s Group by

MySQL’s Group by vs. Oracle’s Group by

Group by məntiqini yəqin ki hər kəs bilir. Fundamental SQL-ə daxildir.
MySQL-in default Group by behave-inə Oracle-ın default-u ilə birlikdə baxacıq.
Ən sonda da MySQL-in Oracle-a (Oracle like MySQL) oxşar şəkildə işlədilməsinə baxacıq.

İLk öncə default sql_mode ilə çalışan MySQL server-ə baxaq:

mysql> select @@global.sql_mode;
+------------------------+
| @@global.sql_mode      |
+------------------------+
| NO_ENGINE_SUBSTITUTION |
+------------------------+
1 row in set (0.00 sec)

Və çox maraqlı bir sorğu ))

-- MySQL
select * from employees group by DEPARTMENT_ID;

Möcüzəli şəkildə görürük ki, normal qaydada result gəldi.
indiki halda sorğumuz hər DEPARTMENT_ID-yə aid 1-ci EMPLOYEE_İD-li işçiləri çıxardır.
Oracle üçün eyni sorğu:

-- Oracle
select * from employees group by department_id;
>>> ORA-00979: not a GROUP BY expression
00979. 00000 -  "not a GROUP BY expression"

Əlbəttə bu belə də olmalı idi ))

Davam edək. İkinci sorğumuz da eyni dərəcədə məntiqsizdir necə deyərlər:

-- MySQL
mysql> select department_id, salary from employees group by department_id;
+---------------+--------+
| department_id | salary |
+---------------+--------+
|             1 |  89949 |
|             2 |  99178 |
|             3 |  53465 |
|             4 |  42566 |
|             5 |  57778 |
|             6 |  80147 |
|             7 |  69412 |
.
.

Yenə default MySQL-də result gəlir. Burda da group by şərtimizə uyğun olaraq hər department_id-yə uyğun 1-ci salary qayıdır.

-- Oracle
select department_id, salary from employees group by department_id;
>>> ORA-00979: not a GROUP BY expression
00979. 00000 -  "not a GROUP BY expression"

Belə tip ERROR-ların gəlməsi bizi daha düzgün sorğu məntiqi qurmağa məcbur edir. Bu çox gözəldir.

Davam edək və daha bir sorğuya baxaq.

-- MySQL

mysql> select DEPARTMENT_ID,employee_id, sum(salary) from employees group by DEPARTMENT_ID;
+---------------+-------------+-------------+
| DEPARTMENT_ID | employee_id | sum(salary) |
+---------------+-------------+-------------+
|             1 |           2 |     3696222 |
|             2 |          53 |     6434950 |
|             3 |          16 |     6802927 |
|             4 |          35 |     7087003 |
|             5 |          20 |     7663093 |
|             6 |           6 |     7987810 |

Gördüyümüz kimi employee_id yuxarıdakı qaydaya uyğun olaraq yenə, department_id-yə uyğun olaraq birincilər gəldi. salary sum() isə düzgün olaraq hesablandı.

Eyni sorğu Oracle-da:

-- Oracle

select DEPARTMENT_ID,employee_id, sum(salary) from employees group by DEPARTMENT_ID;
>>> ORA-00979: not a GROUP BY expression
00979. 00000 -  "not a GROUP BY expression"

Yenidən Oracle bizə ERROR çıxartdır. Çox gözəl.

Eyni sorğu üzərindən employee_id-ni də group by-a salaq.

-- MySQL
mysql> select DEPARTMENT_ID,employee_id, sum(salary) from employees group by DEPARTMENT_ID,employee_id order by DEPARTMENT_ID;
+---------------+-------------+--------+
| DEPARTMENT_ID | employee_id | salary |
+---------------+-------------+--------+
|             1 |           2 |  89949 |
|             1 |          10 |  86809 |
|             1 |          15 |  63270 |
|             1 |          21 |  98654 |
|             1 |          81 |  63036 |
|             1 |         106 |  41379 |
|             1 |         109 |  93638 |
|             1 |         178 |  44590 |
|             1 |         211 |  48328 |
|             1 |         242 |  91293 |


-- Oracle
select DEPARTMENT_ID, employee_id, sum(salary) from employees group by DEPARTMENT_ID, employee_id order by department_id;
>>>
DEPARTMENT_İD     EMPLOYEE_İD     SUM(SALARY)
10	          200	          4400
20	          201 	          13000
20	          202	          6000
30	          114	          11000
30	          115	          3100
30	          116	          2900
30	          117	          2800

Eyni nəticəni çıxartdılar. Hər bir departamenti ayrıca sıralamaqla hər bi işçinin salary-sini ayrı-ayrı çıxadır. Dolayısı ilə burda SUM məntiqsizlik üzündən öz qüvvəsini itirir.
Hər bir departamantə uyğun hər bir işçinin maaşının cəmini tapmaq olmur😉

NƏTİCƏ:
MySQL-dən əgər default konfiqurasiyalı istifadə edəciksə hər bir yazdığımız sorğunu dəfələrlə test etməli, ən azından group by məntiqini düzgün qurmalıyıq.
Oracle-da isə düzgün yazmasanız onszu da ERROR çıxacaq. Təbrik edəcək ))

MySQL-i məhz bu GROUP BY halında Oracle-a bənzər şəkildə ERROR-lar verib bizi xəbərdar etməsini necə təmin edə bilərik.
Bunun üçün MySQL SQL_MODE-da dəyişiklik etməliyik.
my.cnf faylına aşağıdakı sətri [mysqld] kataloqu altında qeyd edirik:

sql_mode = ONLY_FULL_GROUP_BY

MySQL-ə restart veririk.
Indi isə əvvəl düzgün işləyən hər sorğunu sınayaq:

-- 1
mysql> select * from employees group by department_id;
ERROR 1055 (42000): 'mysqlspp.employees.EMPLOYEE_ID' isn't in GROUP BY

-- 2
mysql> select department_id, salary from employees group by department_id;
ERROR 1055 (42000): 'mysqlspp.employees.SALARY' isn't in GROUP BY

-- 3
mysql> select DEPARTMENT_ID,employee_id, sum(salary) from employees group by DEPARTMENT_ID;
ERROR 1055 (42000): 'mysqlspp.employees.EMPLOYEE_ID' isn't in GROUP BY

Gördüyümüz kimi daha əvvəl düzgün işləyən sorğular indi ERROR verir.
Bu şəkildə etməklə biz MySQL-in daha strict şəkildə Oracle kimi çalışmasını təmin etmiş oluruq.

* ƏLAVƏ *
Having-i də test edib bura yazmağa qərar verdim.
sql_mode = ” etdikdən sonra
Bərabər şəkildə düzgün işləyən sorğular:

-- Oracle

select DEPARTMENT_ID,
avg(salary),
count(*)
from employees
group by DEPARTMENT_ID
having avg(salary) > 10000;

-- MySQL

select DEPARTMENT_ID,
avg(salary),
count(*)
from employees
group by DEPARTMENT_ID
having avg(salary) > 70000;

Lakin ALİAS verdikdə fərqlilik ortaya çıxır:


-- Oracle

select DEPARTMENT_ID,
avg(salary) as avgx,
count(*)
from employees
group by DEPARTMENT_ID
having avgx > 10000;

>>> ORA-00904: "AVGX": invalid identifier
00904. 00000 -  "%s: invalid identifier"

-- MySQL

select DEPARTMENT_ID,
avg(salary) as avgx,
count(*)
from employees
group by DEPARTMENT_ID
having avgx > 70000;

+---------------+------------+----------+
| DEPARTMENT_ID | avgx       | count(*) |
+---------------+------------+----------+
|             1 | 71081.1923 |       52 |
|             5 | 72293.3302 |      106 |
|             6 | 73282.6606 |      109 |
|             8 | 70504.3158 |       95 |
|             9 | 73321.0227 |       88 |
|            13 | 71513.8165 |      109 |
|            15 | 70468.3707 |      116 |
|            16 | 70079.0294 |      102 |
|            17 | 70019.2455 |      110 |
|            20 | 72301.6667 |       57 |
+---------------+------------+----------+

Yenə də əgər istəsək ki, məhz bu davranışın da qarşısını alaq o zaman sql_mode-da dəyişiklik etməliyik:

mysql> set @@sql_mode = 'ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)


mysql> select DEPARTMENT_ID,
avg(salary) as avgx,
count(*)
from employees
group by DEPARTMENT_ID
having avgx > 70000;

ERROR 1463 (42000): Non-grouping field 'avgx' is used in HAVING clause

Təşəkkürlər ))

  1. Hələlik heç bir şərh yoxdur
  1. No trackbacks yet.

Bir cavab yazın

Sistemə daxil olmaq üçün məlumatlarınızı daxil edin və ya ikonlardan birinə tıklayın:

WordPress.com Loqosu

WordPress.com hesabınızdan istifadə edərək şərh edirsinz. Çıxış / Dəyişdir )

Twitter rəsmi

Twitter hesabınızdan istifadə edərək şərh edirsinz. Çıxış / Dəyişdir )

Facebook fotosu

Facebook hesabınızdan istifadə edərək şərh edirsinz. Çıxış / Dəyişdir )

Google+ foto

Google+ hesabınızdan istifadə edərək şərh edirsinz. Çıxış / Dəyişdir )

%s qoşulma

%d bloqqer bunu bəyənir: