Aggregation និង Grouping
មាតិកា
- ពីជួរទៅចម្លើយ
- Aggregate Function
- COUNT(*) ទល់នឹង COUNT(column)
- GROUP BY៖ មួយជួរលទ្ធផលក្នុងមួយក្រុម
- ច្បាប់មាសនៃ GROUP BY
- WHERE ទល់នឹង HAVING
- ការ Aggregate កាត់តាម Join៖ របាយការណ៍ចំណូល
- ការរក្សាអតិថិជនដែលមានសូន្យ
- ការដាក់ជាក្រុមតាមខែដោយ date_trunc
- របៀបដែល NULL ប្រព្រឹត្តក្នុង Aggregate
- string_agg និង Clause FILTER
- ការរាប់ឲ្យត្រឹមត្រូវដោយ DISTINCT
- លំដាប់នៃការវាយតម្លៃ ម្តងទៀត
- សាកល្បងដោយខ្លួនឯង
1. ពីជួរទៅចម្លើយ
រហូតមកដល់ពេលនេះ query នីមួយៗត្រឡប់ជួរដាច់ដោយឡែក៖ អតិថិជនម្នាក់ order មួយ line មួយ។ ប៉ុន្តែសំណួរអាជីវកម្មជាធម្មតាអំពី ផលបូក៖ យើងទទួលបាន order ប៉ុន្មាន? ចំណូលរបស់យើងប៉ុន្មាន? ប្រភេទណាលក់ដាច់ជាងគេ? គ្មានអ្នកណាចង់ស្កេនរាប់ពាន់ជួរ ហើយបូកក្នុងក្បាលទេ។
Aggregation បង្រួមជួរច្រើនទៅជាតម្លៃមួយ (ឬតម្លៃមួយក្នុងមួយក្រុម)។ វាជាភាពខុសគ្នារវាងបញ្ជី order និងរបាយការណ៍លក់ ហើយ database ធ្វើវាក្នុង query តែមួយ លឿនជាងការទាញរាល់ជួរចូលកម្មវិធីរបស់អ្នក ហើយ loop ឆ្ងាយណាស់។
រក្សាទុក query នៃជំពូកនេះក្នុង shopdb/queries/08_aggregation.sql។ ដំណើរការវាដោយ៖
docker exec -i shopdb-pg psql -U postgres -d shopdb < queries/08_aggregation.sql
2. Aggregate Function
aggregate function យកសំណុំនៃតម្លៃមកត្រឡប់តម្លៃតែមួយ។ ប្រាំដែលអ្នកនឹងប្រើជារៀងរាល់ថ្ងៃ៖
| Function | ត្រឡប់ |
|---|---|
COUNT(...) | ចំនួនជួរ (ឬតម្លៃដែលមិនមែន null) |
SUM(x) | ផលបូកនៃ x |
AVG(x) | មធ្យមភាគនៃ x |
MIN(x) | x តូចបំផុត |
MAX(x) | x ធំបំផុត |
បើគ្មាន GROUP BY aggregate ចាត់ទុក table ទាំងមូល ជាក្រុមតែមួយ៖
SELECT count(*) AS products,
sum(price) AS total_price,
round(avg(price), 2) AS avg_price,
min(price) AS cheapest,
max(price) AS priciest
FROM products;
products | total_price | avg_price | cheapest | priciest
----------+-------------+-----------+----------+----------
8 | 197.50 | 24.69 | 5.50 | 79.00
(1 row)
ផលិតផលប្រាំបីដែលតម្លៃរបស់វាបូកបាន 197.50 ដូច្នេះមធ្យមភាគគឺ 197.5 / 8 = 24.6875 ដែលយើងបង្គត់ទៅ 24.69 សម្រាប់ការបង្ហាញ។ ត្រូវ round(avg(...), 2) ជានិច្ចសម្រាប់លុយ៖ avg លើ column ប្រភេទ numeric ត្រឡប់ខ្សែកន្ទុយវែងនៃខ្ទង់ទសភាគ។
សូមកត់សម្គាល់ថាលទ្ធផលគឺ មួយជួរ ទោះមានផលិតផលប៉ុន្មានក៏ដោយ។ នោះហើយជាអ្វីដែល aggregation ធ្វើ។
MIN និង MAX ក៏ដំណើរការលើអក្សរ និងកាលបរិច្ឆេទដែរ៖ ឈ្មោះផលិតផលដែលនៅមុនគេតាមលំដាប់អក្ខរក្រម ឬ ordered_at ដំបូងបំផុត។
3. COUNT(*) ទល់នឹង COUNT(column)
ទាំងនេះមើលទៅស្រដៀងគ្នា ប៉ុន្តែផ្តល់ចម្លើយខុសគ្នាពេលមាន NULL។
COUNT(*)រាប់ ជួរ។COUNT(city)រាប់ជួរដែលcityមិនមែន NULL។
SELECT count(*) AS customers,
count(city) AS with_city
FROM customers;
customers | with_city
-----------+-----------
5 | 4
(1 row)
Maly Ros គ្មាន city ដូច្នេះ count(city) រំលងនាង។ នេះគឺជាវិធីស្តង់ដារដើម្បីសួរថា "តើមានប៉ុន្មានជួរដែលបំពេញ field នេះ?"
ទម្រង់ទីបី COUNT(DISTINCT city) រាប់ចំនួននៃតម្លៃខុសៗគ្នាដែលមិនមែន null។ នៅទីនេះគឺ 3 (Phnom Penh, Siem Reap, Battambang) ទោះបីអតិថិជនបួននាក់មាន city។
4. GROUP BY៖ មួយជួរលទ្ធផលក្នុងមួយក្រុម
ថាមពលពិតមកជាមួយ GROUP BY។ វាបំបែកជួរទៅជាក្រុមដែលចែករំលែកតម្លៃដូចគ្នា បន្ទាប់មកដំណើរការ aggregate ម្តងក្នុងមួយក្រុម។
តើមាន order ប៉ុន្មានក្នុងស្ថានភាពនីមួយៗ?
SELECT status, count(*) AS orders
FROM orders
GROUP BY status
ORDER BY status;
status | orders
-----------+--------
cancelled | 1
paid | 2
pending | 1
shipped | 1
(4 rows)
គិតថាវាជាបីជំហាន។ PostgreSQL ប្រមូល order ទាំងប្រាំ ដាក់ចូលធុងតាម status បន្ទាប់មករាប់ធុងនីមួយៗ។ ស្ថានភាពខុសៗគ្នាបួន ដូច្នេះបួនជួរ ហើយចំនួនរាប់បូកបាន 5 ដើម។
អ្នកអាចដាក់ជាក្រុមតាម column ច្រើន និងតាម expression ។ គំនិតដូចគ្នាអនុវត្តលើអតិថិជនតាម city៖
SELECT city, count(*) AS customers
FROM customers
GROUP BY city
ORDER BY city;
city | customers
------------+-----------
Battambang | 1
Phnom Penh | 2
Siem Reap | 1
| 1
(4 rows)
NULL ត្រូវបានចាត់ទុកជាក្រុមមួយផ្ទាល់ខ្លួន ដូច្នេះ Maly លេចឡើងជាជួរមួយដែល city ទទេ។ តាមលំនាំដើម PostgreSQL តម្រៀប NULL ចុងក្រោយក្នុងលំដាប់ឡើង។
5. ច្បាប់មាសនៃ GROUP BY
នេះគឺជាច្បាប់ដែលបង្កកំហុសអ្នកចាប់ផ្តើមភាគច្រើន៖
រាល់ column ក្នុង
SELECTត្រូវតែនៅក្នុងGROUP BYឬនៅក្នុង aggregate function។
ហេតុអ្វី? បន្ទាប់ពីដាក់ជាក្រុម ជួរលទ្ធផលនីមួយៗតំណាងឲ្យជួរដើមច្រើន។ ប្រសិនបើអ្នកសុំ name ប៉ុន្តែដាក់ជាក្រុមតាម city តើឈ្មោះណាមួយក្នុងក្រុមដែលត្រូវបង្ហាញ? database បដិសេធមិនទាយ៖
SELECT city, name, count(*)
FROM customers
GROUP BY city;
ERROR: column "customers.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT city, name, count(*)
^
(ពាក្យពិតប្រាកដខុសគ្នាបន្តិចរវាងកំណែ PostgreSQL។) ដោះស្រាយវាដោយគិតអំពីអ្វីដែលអ្នកពិតជាចង់បាន៖ បន្ថែម name ទៅក្នុង GROUP BY (បន្ទាប់មកក្រុមនីមួយៗជាអតិថិជនម្នាក់ ដែលមិនមែនជាការសង្ខេបមានប្រយោជន៍) ឬ aggregate វាដោយអ្វីមួយដូចជា min(name) ឬ string_agg។
ករណីពិសេសងាយស្រួលមួយ៖ ប្រសិនបើអ្នកដាក់ជាក្រុមតាម primary key របស់ table PostgreSQL ដឹងថា column ផ្សេងទៀតទាំងអស់នៃ table នោះត្រូវបានកំណត់ដោយវា ដូច្នេះ GROUP BY c.id អនុញ្ញាតឲ្យអ្នក select c.name ផងដែរ។ មនុស្សជាច្រើននៅតែសរសេរទាំងពីរ (GROUP BY c.id, c.name) ដែលដំណើរការគ្រប់ទីកន្លែង ហើយមានសុវត្ថិភាពជានិច្ច។
6. WHERE ទល់នឹង HAVING
ទាំងពីរ filter ប៉ុន្តែនៅពេលខុសគ្នា៖
WHEREfilter ជួរ មុន ដាក់ជាក្រុម។HAVINGfilter ក្រុម បន្ទាប់ពី aggregation។
អ្នកមិនអាចប្រើ aggregate ក្នុង WHERE បានទេ ព្រោះក្រុមមិនទាន់មាននៅឡើយ។ នេះបរាជ័យ៖
SELECT customer_id, count(*)
FROM orders
WHERE count(*) >= 2 -- wrong
GROUP BY customer_id;
ERROR: aggregate functions are not allowed in WHERE
ឧបករណ៍ត្រឹមត្រូវគឺ HAVING។ តើអតិថិជនណាខ្លះបានដាក់ order យ៉ាងហោចណាស់ពីរ?
SELECT c.name, count(o.id) AS orders
FROM customers c
JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name
HAVING count(o.id) >= 2
ORDER BY c.name;
name | orders
------------+--------
Dara Kim | 2
Sokha Chan | 2
(2 rows)
ពេលត្រូវការទាំងពីរ សូមប្រើនីមួយៗសម្រាប់ការងាររបស់វា៖ WHERE ដើម្បីទម្លាក់ជួរដែលអ្នកមិនចង់ឲ្យរាប់ (ឧទាហរណ៍ order ដែលបានលុបចោល) HAVING ដើម្បីរក្សាតែក្រុមដែលឆ្លងកាត់កម្រិត។ ការ filter ជួរដោយ WHERE ជាមុនក៏លឿនជាងដែរ ព្រោះមានអ្វីតិចជាងត្រូវដាក់ជាក្រុម។
7. ការ Aggregate កាត់តាម Join៖ របាយការណ៍ចំណូល
ឥឡូវផ្សំជំពូកទី 7 ជាមួយជំពូកនេះ។ សរុបនៃ order មួយគឺជាផលបូកនៃ line របស់វា ដែល line នីមួយៗគឺ quantity * unit_price៖
SELECT order_id,
sum(quantity * unit_price) AS total
FROM order_items
GROUP BY order_id
ORDER BY order_id;
order_id | total
----------+-------
1 | 26.00
2 | 79.00
3 | 60.50
4 | 57.50
5 | 22.00
(5 rows)
ពិនិត្យ order 1 ដោយដៃ៖ 1 x 15.00 បូក 2 x 5.50 គឺ 15.00 + 11.00 = 26.00។
ចំណូលក្នុងមួយអតិថិជនត្រូវការ table បី៖ customers, orders, lines។
SELECT c.name,
sum(oi.quantity * oi.unit_price) AS revenue
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN order_items oi ON oi.order_id = o.id
GROUP BY c.id, c.name
ORDER BY revenue DESC;
name | revenue
------------+---------
Sokha Chan | 105.00
Dara Kim | 82.50
Linda Vong | 57.50
(3 rows)
Sokha៖ 26.00 + 79.00 = 105.00។ Dara៖ 60.50 + 22.00 = 82.50 (នេះរួមបញ្ចូល order ដែលបានលុបចោលរបស់នាង ជាចំណុចដែលយើងកែខាងក្រោម)។ Linda៖ 57.50។
សូមកត់សម្គាល់ថាយើងអាច ORDER BY revenue ដែលជា alias ព្រោះ ORDER BY ដំណើរការបន្ទាប់ពី SELECT។ ហើយចំណូលក្នុងមួយប្រភេទឆ្លងកាត់ products៖
SELECT cat.name AS category,
sum(oi.quantity * oi.unit_price) AS revenue,
sum(oi.quantity) AS units_sold
FROM order_items oi
JOIN products p ON p.id = oi.product_id
JOIN categories cat ON cat.id = p.category_id
GROUP BY cat.name
ORDER BY revenue DESC;
category | revenue | units_sold
-------------+---------+------------
Electronics | 135.00 | 6
Books | 70.00 | 3
Home | 40.00 | 4
(3 rows)
សូមចំណាំថាយើងបានប្រើ oi.unit_price (តម្លៃនៅពេលលក់) មិនមែន p.price (តម្លៃថ្ងៃនេះ) ទេ។ ប្រសិនបើតម្លៃប្តូរនៅខែក្រោយ ចំណូលចាស់មិនគួរប្តូរទេ។ នោះហើយជាមូលហេតុដែល order_items រក្សាទុកច្បាប់ចម្លងផ្ទាល់ខ្លួន ជាចំណុចដែលជំពូកទី 10 ត្រឡប់មករកវិញ។
order ដែលបានលុបចោលមិនគួរត្រូវរាប់ជាចំណូលទេ។ នោះគឺជាលក្ខខណ្ឌ WHERE ព្រោះវា filter ជួរមុនដាក់ជាក្រុម៖
SELECT c.name,
sum(oi.quantity * oi.unit_price) AS revenue
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN order_items oi ON oi.order_id = o.id
WHERE o.status <> 'cancelled'
GROUP BY c.id, c.name
ORDER BY revenue DESC;
ចំណូលរបស់ Dara ធ្លាក់ពី 82.50 ទៅ 60.50 ព្រោះ order ដែលបានលុបចោលរបស់នាង (22.00) បាត់ទៅ។
8. ការរក្សាអតិថិជនដែលមានសូន្យ
របាយការណ៍ចំណូលខាងលើបញ្ជីតែ 3 ក្នុងចំណោមអតិថិជន 5 នាក់។ Vuthy និង Maly គ្មាន order ដូច្នេះ inner join បានលុបពួកគេចោល។ ដើម្បីបញ្ជី ទាំងអស់គ្នា សូមប្រើ LEFT JOIN ដូចដែលអ្នកបានរៀនក្នុងជំពូកមុន។ ប៉ុន្តែ SUM លើគ្មានជួរត្រឡប់ NULL មិនមែនសូន្យទេ ដូច្នេះរុំវាដោយ COALESCE៖
SELECT c.name,
coalesce(sum(oi.quantity * oi.unit_price), 0) AS revenue
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
LEFT JOIN order_items oi ON oi.order_id = o.id
GROUP BY c.id, c.name
ORDER BY revenue DESC, c.name;
name | revenue
------------+---------
Sokha Chan | 105.00
Dara Kim | 82.50
Linda Vong | 57.50
Maly Ros | 0.00
Vuthy Sok | 0.00
(5 rows)
join ទាំងពីរត្រូវតែជា LEFT។ ប្រសិនបើទីពីរជា JOIN ធម្មតា ជួរដែលគ្មាន order នឹងត្រូវទម្លាក់ម្តងទៀតនៅជំហាននោះ។
c.name បន្ថែមក្នុង ORDER BY បំបែកភាពស្មើគ្នារវាងជួរសូន្យទាំងពីរ ដូច្នេះលំដាប់លទ្ធផលនឹងថេរ។
9. ការដាក់ជាក្រុមតាមខែដោយ date_trunc
របាយការណ៍តាមខែមានគ្រប់ទីកន្លែង។ date_trunc('month', ts) បង្គត់ timestamp ចុះទៅខណៈដំបូងនៃខែរបស់វា ដោយផ្តល់តម្លៃមួយក្នុងមួយខែដើម្បីដាក់ជាក្រុម៖
SELECT date_trunc('month', o.ordered_at)::date AS month,
sum(oi.quantity * oi.unit_price) AS revenue
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
WHERE o.status <> 'cancelled'
GROUP BY date_trunc('month', o.ordered_at)
ORDER BY month;
month | revenue
------------+---------
2026-01-01 | 105.00
2026-02-01 | 118.00
(2 rows)
ពិនិត្យខែមករា៖ order 1 និង 2, 26.00 + 79.00 = 105.00។ ខែកុម្ភៈដោយគ្មាន order 5 ដែលបានលុបចោល៖ order 3 (60.50) បូក order 4 (57.50) គឺ 118.00។ ::date cast គ្រាន់តែកាត់ម៉ោងនៃថ្ងៃចោលសម្រាប់ការបង្ហាញ។ (ការរួមបញ្ចូល order ដែលបានលុបចោលនឹងធ្វើឲ្យខែកុម្ភៈ 140.00។)
function ដូចគ្នាទទួល 'day', 'week', 'year' និងផ្សេងទៀត។ ក្នុង PostgreSQL អ្នកក៏អាចសរសេរ GROUP BY 1 មានន័យថា "column ទីមួយក្នុងបញ្ជី SELECT" ជាផ្លូវកាត់ដែលងាយស្រួល ប៉ុន្តែអានពិបាកជាង។
10. របៀបដែល NULL ប្រព្រឹត្តក្នុង Aggregate
Aggregate function មិនអើពើនឹងតម្លៃ NULL (លើកលែង COUNT(*) ដែលរាប់ជួរ)។ នេះជាធម្មតាជាអ្វីដែលអ្នកចង់បាន ប៉ុន្តែវាអាចធ្វើឲ្យយល់ច្រឡំ។
SELECT avg(x) AS average
FROM (VALUES (1), (NULL), (3)) AS t(x);
average
--------------------
2.0000000000000000
(1 row)
មធ្យមភាគគឺ 2 មិនមែន 4/3 ទេ ព្រោះជួរ NULL ត្រូវបានរំលង៖ (1 + 3) ចែកនឹង 2 តម្លៃ។ ប្រសិនបើអ្នកមានន័យថា "ចាត់ទុកតម្លៃដែលបាត់ជាសូន្យ" ត្រូវនិយាយវាឲ្យច្បាស់ដោយ avg(coalesce(x, 0)) ដែលនឹងផ្តល់ 1.33។
ការពិតពីរបន្ថែមទៀតដែលត្រូវចងចាំ៖
SUMនៃសំណុំទទេ (គ្មានជួរ ឬNULLទាំងអស់) គឺNULLមិនមែន 0 ទេ។ ប្រើcoalesce(sum(...), 0)។COUNTនៃសំណុំទទេគឺ 0 មិនដែលជាNULLទេ។
ពេល column អាចជា null សូមសម្រេចដោយចេតនាថា aggregate គួរធ្វើអ្វីជាមួយវា។
11. string_agg និង Clause FILTER
លក្ខណៈពិសេស PostgreSQL ពីរដែលគួរដឹងតាំងពីដំបូង។
string_agg(expr, separator) ភ្ជាប់តម្លៃនៃក្រុមមួយទៅជាតម្លៃអក្សរតែមួយ។ តើផលិតផលណាខ្លះនៅក្នុងប្រភេទនីមួយៗ?
SELECT cat.name AS category,
string_agg(p.name, ', ' ORDER BY p.name) AS products
FROM categories cat
JOIN products p ON p.category_id = cat.id
GROUP BY cat.name
ORDER BY cat.name;
category | products
-------------+------------------------------------------------
Books | Clean Code, Notebook Pack, SQL Cookbook
Electronics | Mechanical Keyboard, USB-C Cable, Wireless Mouse
Home | Coffee Mug, Desk Lamp
(3 rows)
ORDER BY នៅក្នុងវង់ក្រចកគ្រប់គ្រងលំដាប់ក្នុងខ្សែអក្សរដែលបានភ្ជាប់នីមួយៗ។ (ចន្លោះក្នុង terminal របស់អ្នកនឹងខុសគ្នាបន្តិចតាមតម្លៃទូលាយបំផុតក្នុង column។)
FILTER (WHERE ...) ភ្ជាប់លក្ខខណ្ឌទៅនឹង aggregate តែមួយ ដូច្នេះអ្នកអាចគណនាលេខច្រើនដែល filter ខុសៗគ្នាក្នុងការឆ្លងកាត់តែមួយ។ ចំណូលសរុប និងចំណូលតែ order ដែលបានបង់ប្រាក់ក្នុងមួយខែ ក្បែរគ្នា៖
SELECT date_trunc('month', o.ordered_at)::date AS month,
sum(oi.quantity * oi.unit_price) AS total,
sum(oi.quantity * oi.unit_price)
FILTER (WHERE o.status = 'paid') AS paid_only
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
GROUP BY date_trunc('month', o.ordered_at)
ORDER BY month;
month | total | paid_only
------------+--------+-----------
2026-01-01 | 105.00 | 26.00
2026-02-01 | 140.00 | 57.50
(2 rows)
ខែមករា៖ order 1 (បានបង់ប្រាក់ 26.00) និង 2 (បានដឹកជញ្ជូន 79.00) ដូច្នេះសរុប 105.00 ហើយបានបង់ប្រាក់ 26.00។ ខែកុម្ភៈ៖ order 3, 4, 5 សរុប 60.50 + 57.50 + 22.00 = 140.00 ដែលមានតែ order 4 ប៉ុណ្ណោះបានបង់ប្រាក់។
បើគ្មាន FILTER អ្នកនឹងសរសេរ SUM(CASE WHEN status = 'paid' THEN ... ELSE 0 END) ដែលធ្វើការដូចគ្នាតែក្នុងរបៀបដែលរញ៉េរញ៉ៃជាង។
12. ការរាប់ឲ្យត្រឹមត្រូវដោយ DISTINCT
ជំពូកមុនបានព្រមានអំពីការគុណជួរ។ នេះគឺជារបៀបដែលវាខាំក្នុង aggregate។ យើងចង់បាន "ចំនួន order ក្នុងមួយអតិថិជន" ដោយ join ចុះដល់ line៖
SELECT c.name,
count(o.id) AS wrong,
count(DISTINCT o.id) AS right
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN order_items oi ON oi.order_id = o.id
GROUP BY c.id, c.name
ORDER BY c.id;
name | wrong | right
------------+-------+-------
Sokha Chan | 3 | 2
Dara Kim | 3 | 2
Linda Vong | 3 | 1
(3 rows)
Sokha មាន 2 order ប៉ុន្តែ 3 line (order 1 មានពីរ order 2 មានមួយ) ដូច្នេះ count(o.id) រាប់ order នីមួយៗម្តងក្នុងមួយ line។ count(DISTINCT o.id) រាប់ id របស់ order នីមួយៗម្តង។ ប្រសិនបើអ្នកត្រូវការតែ order កុំ join ទៅ line សោះ។ ប្រសិនបើអ្នកត្រូវការទាំង order និងលេខកម្រិត line សូមប្រើ DISTINCT ឬ aggregate line ក្នុង subquery ជាមុន (ជំពូកបន្ទាប់)។
អន្ទាក់ដូចគ្នាអនុវត្តចំពោះ SUM៖ ការបូក column កម្រិត order បន្ទាប់ពី join ទៅ line រាប់វាម្តងក្នុងមួយ line។ Aggregate នៅកម្រិតដែល column នោះជាកម្មសិទ្ធិ។
13. លំដាប់នៃការវាយតម្លៃ ម្តងទៀត
ជំពូកទី 5 បានផ្តល់លំដាប់តក្កវិជ្ជានៃ query។ ឥឡូវវាមានជំហានច្រើនជាង៖
1. FROM / JOIN build the combined rows
2. WHERE drop rows
3. GROUP BY make groups
4. HAVING drop groups
5. SELECT compute output columns (aggregates, aliases)
6. ORDER BY sort
7. LIMIT cut
នេះពន្យល់ច្បាប់ដែលអ្នកបានជួប៖
WHEREមិនអាចប្រើ aggregate បានទេ៖ ក្រុមមិនទាន់មាននៅជំហានទី 2។HAVINGអាចប្រើ aggregate បាន៖ វាដំណើរការបន្ទាប់ពីជំហានទី 3។ORDER BYអាចប្រើ alias របស់ column បាន ប៉ុន្តែWHEREនិងHAVINGមិនអាចទេ ព្រោះ alias ត្រូវបានបង្កើតនៅជំហានទី 5 បន្ទាប់ពីពួកវា។
ពេល query បរាជ័យដោយមានកំហុសចម្លែក សូមដើរកាត់ជំហានទាំងនេះ ហើយសួរថាជំហានណាត្រូវការអ្វីដែលអ្នកកំពុងប្រើ ហើយតើវាមានរួចឬនៅ។ រក្សាទុក query ទាំងអស់របស់អ្នកពីជំពូកនេះក្នុង shopdb/queries/08_aggregation.sql។
14. សាកល្បងដោយខ្លួនឯង
ពិនិត្យលទ្ធផលនីមួយៗជាមួយ seed data ដោយដៃបើអាច។
- រកតម្លៃមធ្យម តូចបំផុត និងធំបំផុតនៃផលិតផលក្នុងប្រភេទ
Books។ (Join ទៅcategoriesឬប្រើcategory_id = 2។) បង្គត់មធ្យមភាគទៅ 2 ខ្ទង់ទសភាគ។ - រាប់ផលិតផលដែលអស់ស្តុក (
stock = 0) និងចំនួនឯកតាសរុបក្នុងស្តុកនៃផលិតផលទាំងអស់។ តើវាជាផលិតផលណាខ្លះ? - បញ្ជីអតិថិជនគ្រប់គ្នាជាមួយចំនួន order ដែលពួកគេបានដាក់ (រួមទាំង 0 សម្រាប់អ្នកដែលគ្មាន)។ ប្រើ
LEFT JOINនិងcount(o.id)។ បន្ទាប់មកប្តូរcount(o.id)ទៅcount(*)ហើយពន្យល់ថាហេតុអ្វី Vuthy និង Maly ឥឡូវបង្ហាញ 1។ - បង្ហាញតែអតិថិជនដែលចំណូលសរុបរបស់ពួកគេ (មិនរាប់ order ដែលបានលុបចោល) លើសពី 60.00 ដោយប្រើ
HAVING។ អ្នកណាមានលក្ខណៈសម្បត្តិគ្រប់គ្រាន់? - សម្រាប់ប្រភេទនីមួយៗ បង្ហាញចំនួនផលិតផលខុសៗគ្នា និងបញ្ជីឈ្មោះផលិតផលដោយ
string_agg។ បន្ថែម column មួយដែលមានតម្លៃមធ្យមបង្គត់ទៅ 2 ខ្ទង់ទសភាគ។ - សម្រាប់ស្ថានភាព order នីមួយៗ បង្ហាញ
count(DISTINCT customer_id)និងចំនួន order line។ តើស្ថានភាពណាមាន line ច្រើនជាងគេ ហើយហេតុអ្វីវាមិនត្រូវនឹងចំនួន order?
ទៅទីណាបន្ត។ ឥឡូវអ្នកអាចសាងសង់របាយការណ៍រឹងមាំក្នុង query តែមួយ។ ក្នុង Subquery, CTE និង Window Function អ្នកនឹងរៀនបំបែកសំណួរធំៗទៅជាជំហានដែលមានឈ្មោះ រក្សាទុករបាយការណ៍ជា view និងដាក់ចំណាត់ថ្នាក់ជួរ ឬគណនាផលបូកបន្តបន្ទាប់ដោយមិនបង្រួមវាទៅជាក្រុម។
ទិញកាហ្វេជូនខ្ញុំ
ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!