Рішення
%%sql
SELECT DISTINCT user_id
FROM user_actions
ORDER BY user_id| user_id | |
|---|---|
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| ... | ... |
| 21396 | 21398 |
| 21397 | 21399 |
| 21398 | 21400 |
| 21399 | 21401 |
| 21400 | 21402 |
21401 rows × 1 columns
DISTINCTКлючове слово DISTINCT дає змогу відбирати унікальні записи, тобто позбавлятися всіх дублікатів у таблиці.
Вказується DISTINCT одразу після SELECT. Для виведення унікальних значень в одній колонці можна скласти наступний запит:
SELECT DISTINCT column
FROM tableДавайте спершу вирішимо просте завдання.
Завдання 16.1
Виведіть ID всіх унікальних користувачів з таблиці user_actions. Результат відсортуйте за зростанням id.
Поле у результуючій таблиці: user_id
%%sql
SELECT DISTINCT user_id
FROM user_actions
ORDER BY user_id| user_id | |
|---|---|
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| ... | ... |
| 21396 | 21398 |
| 21397 | 21399 |
| 21398 | 21400 |
| 21399 | 21401 |
| 21400 | 21402 |
21401 rows × 1 columns
Ключове слово DISTINCT можна застосовувати не тільки до однієї колонки, а й одразу до кількох.
Наприклад, запит для двох колонок виглядатиме так:
SELECT DISTINCT column_1, column_2
FROM tableУ такому випадку запит поверне унікальні комбінації значень в колонках.
Завдання 16.2
Застосуйте DISTINCT відразу до двох колонок таблиці courier_actions та відберіть унікальні пари значень courier_id та order_id.
Результат відсортуйте спочатку за зростанням id кур’єра, потім за зростанням id замовлення.
Поля у результуючій таблиці: courier_id, order_id
%%sql
SELECT DISTINCT courier_id,
order_id
FROM courier_actions
ORDER BY courier_id, order_id| courier_id | order_id | |
|---|---|---|
| 0 | 1 | 98 |
| 1 | 1 | 194 |
| 2 | 1 | 233 |
| 3 | 1 | 522 |
| 4 | 1 | 1251 |
| ... | ... | ... |
| 59590 | 3166 | 56165 |
| 59591 | 3166 | 56940 |
| 59592 | 3167 | 56176 |
| 59593 | 3167 | 58039 |
| 59594 | 3167 | 58774 |
59595 rows × 2 columns
COUNT, SUM, AVG, MIN, MAXАгрегатними функціями називають функції, які обробляють певний набір спостережень і повертають одне узагальнююче значення. Якщо ви коли-небудь працювали в Excel, то, напевно, стикалися з підрахунком суми або максимального/мінімального значення по стовпцю — йдеться саме про це.
Ось кілька прикладів таких функцій у SQL:
COUNT: повертає кількість значень у колонці;SUM: обчислює суму значень;AVG: обчислює середнє значення;MAX: обчислює максимальне значення;MIN: обчислює мінімальне значення.Приклад:
SELECT COUNT(column) AS count
FROM table
SELECT SUM(column_1) AS sum,
AVG(column_2) AS average
FROM tableЗверніть увагу, що деякі з вищезгаданих функцій не можна застосовувати до колонок з текстом, датами та часом, оскільки не цілком зрозуміло, що, наприклад, означає знайти середнє значення або суму найменувань товарів.
У той самий час «максимальне» найменування товару обчислити можна — функція MAX шукатиме найбільше значення упорядкованої послідовності (відповідно до встановлених правил сортування значень рядкового типу).
Втім, заучувати межі застосування цих функцій не потрібно — просто керуйтеся здоровим глуздом.
Докладніше про агрегатні функції в DuckDB можна ознайомитися тут.
Завдання 16.3
Порахуйте максимальну та мінімальну ціни товарів у таблиці products. Поля назвіть відповідно max_price, min_price.
Поля у результуючій таблиці: max_price, min_price
Пояснення: в одному запиті можна використовувати відразу кілька агрегаційних функцій — якщо необхідно, то навіть по кількох різних колонках.
%%sql
SELECT max(price) as max_price,
min(price) as min_price
FROM products| max_price | min_price | |
|---|---|---|
| 0 | 800.0 | 1.0 |
COUNT(*) vs COUNT(column)Також при підрахунку кількості записів іноді замість найменування колонки як атрибут функції COUNT використовують зірочку «*»:
SELECT COUNT(*)
FROM tableОднак важливо враховувати один нюанс: запит із зірочкою повертає кількість взагалі всіх записів у таблиці, а запит із зазначенням стовпця — кількість тих записів, де в заданому стовпці значення не є NULL.
Таким чином, якщо в деякій колонці column є перепустки, вирази COUNT(*) і COUNT(column) повернуть різні значення.
Давайте перевіримо!
Завдання 16.4
Як ви пам’ятаєте, у таблиці users в деяких користувачів не було зазначено їх дати народження.
Порахуйте в одному запиті кількість усіх записів у таблиці та кількість лише тих записів, для яких у колонці birth_date вказана дата народження.
Колонку із загальним числом записів назвіть dates, а колонку із записами без перепусток — dates_not_null.
Поля у результуючій таблиці: dates, dates_not_null
%%sql
SELECT count(*) as dates,
count(birth_date) as dates_not_null
FROM users| dates | dates_not_null | |
|---|---|---|
| 0 | 20331 | 20281 |
І ще один важливий момент: агрегатні функції можна застосовувати в поєднанні з ключовим словом DISTINCT. У такому випадку розрахунки будуть проводитися лише за унікальними значеннями.
Якщо у випадку з MIN та MAX це не має особливого сенсу, то при розрахунку AVG, SUM та COUNT іноді це буває корисно:
SELECT SUM(DISTINCT column) AS sum_distinct
FROM tableПри цьому досить часто DISTINCT використовується саме в поєднанні з COUNT для підрахунку числа унікальних користувачів, унікальних замовлень тощо.
SELECT COUNT(DISTINCT column) AS count_distinct
FROM tableЗавдання 16.5
Порахуйте кількість всіх значень у колонці user_id у таблиці user_actions, а також кількість унікальних значень у цій колонці (тобто кількість унікальних користувачів сервісу).
Колонку з першим отриманим значенням назвіть users, а колонку з другим – unique_users.
Поля у результуючій таблиці: users, unique_users
%%sql
SELECT count(user_id) as users,
count(distinct user_id) as unique_users
FROM user_actions| users | unique_users | |
|---|---|---|
| 0 | 62574 | 21401 |
А якщо для розрахунків нам потрібні не всі дані в стовпці, а тільки якась частина? Тоді в запит з агрегатними функціями можна включити оператор WHERE, вказавши умову для відбору записів:
SELECT COUNT(column_1) AS count
FROM table
WHERE column_2 > 100У такому випадку спочатку буде виконана фільтрація таблиці і тільки потім буде проведена агрегація по записах, що залишилися.
Про всяк випадок нагадаємо порядок виконання у запиті відомих нам ключових операторів:
SELECT -- перерахування полів результуючої таблиці
FROM -- вказівка джерела даних
WHERE -- фільтрація даних
ORDER BY -- сортування результуючої таблиці
LIMIT -- обмеження кількості записів, що виводятьсяЗавдання 16.6
Порахуйте кількість кур’єрів жіночої статі у таблиці couriers. Отриманий стовпець з одним значенням назвіть couriers.
Поле в результуючій таблиці: couriers
%%sql
SELECT count(distinct courier_id) as couriers
FROM couriers
WHERE sex = 'female'| couriers | |
|---|---|
| 0 | 1149 |
І ще одне завдання на агрегацію із фільтрацією. На цей раз проведемо розрахунки по колонці з даними у форматі TIMESTAMP.
Завдання 16.7
Розрахуйте час, коли було здійснено першу та останню доставку замовлень у таблиці courier_actions.
Колонку з часом першої доставки назвіть first_delivery, а колонку з часом останньої – last_delivery.
Поля у результуючій таблиці: first_delivery, last_delivery
Пояснення: зауважте, що в таблиці з діями кур’єрів є не тільки записи з часом доставки замовлень, але й записи з часом їх прийняття.
%%sql
SELECT min(time) as first_delivery,
max(time) as last_delivery
FROM courier_actions
WHERE action = 'deliver_order'| first_delivery | last_delivery | |
|---|---|---|
| 0 | 2022-08-24 02:15:00 | 2022-09-08 23:59:00 |
У поєднанні з агрегатними функціями можна використовувати ті ж умовні конструкції, які ми розглядали раніше.
Давайте додамо до нашого запиту більш цікаву фільтрацію.
Завдання 16.8
Уявіть, що один із користувачів сервісу зробив замовлення, до якого увійшли одна пачка крекерів (crackers), одна пачка чіпсів (chips) та один енергетичний напій (energy drink). Порахуйте вартість такого замовлення.
Колонку із розрахованою вартістю замовлення назвіть order_price.
Для розрахунків використовуйте таблицю products.
Поле в результуючій таблиці: order_price
Для вирішення завдання необхідно «сформувати» описане замовлення, відібравши з таблиці products зазначені товари та порахувавши їхню сумарну вартість.
%%sql
SELECT sum(price) as order_price
FROM products
WHERE name in ('crackers', 'chips', 'energy drink')| order_price | |
|---|---|
| 0 | 235.0 |
ARRAY_LENGTHЯк пам’ятаєте, у таблиці orders вміст замовлень представлено вигляді списків товарів (масивів). Щоб порахувати кількість товарів у кожному замовленні, можна скористатися функцією array_length.
Функція array_length обчислює кількість елементів у масиві (довжину масиву) і записується так:
SELECT array_length(ARRAY['first', 'second', 'third'], 1)
Результат:
3Синтаксис може здатися вам трохи складним, але це лише на перший погляд! Давайте розбиратися.
ARRAY['first', 'second', 'third'] – це деякий список із трьох значень: 'first', 'second', 'third’.
Одиниця як другий аргумент — це розмірність масиву, за якій рахується його довжина. Так як список у нас одновимірний (просто значення, записані в один рядок), то вибір у нас невеликий – можемо вказати лише першу розмірність.
Якби в нас була таблиця N x N, в якій були б і рядки, і стовпці, то розмірності було б дві: перша відповідала кількості рядків, а друга — числу стовпців. У такому випадку ми могли б вказати або першу, або другу розмірність.
Давайте уявімо, що у нас є проста таблиця наступного виду:
_______
| 1 | 2 |
| 3 | 4 |
| 5 | 6 |
‾‾‾‾‾‾‾У цій таблиці 3 рядки та 2 стовпці, тому її можна описати у вигляді наступного списку з трьох вкладених у нього списків:
ARRAY[[1,2], [3,4], [5,6]]У прикладі вище кількість списків усередині основного списку — кількість рядків у таблиці, а кількість елементів усередині кожного внутрішнього списку — кількість стовпців.
Зверніть увагу на результат обчислень функції array_length для першої та другої розмірності:
SELECT array_length(ARRAY[[1,2], [3,4], [5,6]], 1)
Результат:
3
SELECT array_length(ARRAY[[1,2], [3,4], [5,6]], 2)
Результат:
2У це досить складно повірити, але значеннями в основній таблиці справді можуть бути інші таблиці (матриці). На щастя, у нас не такі дані, тому ми працюватимемо із простими однорозмірними списками значень.
В якості аргументу функції array_length на місці масиву можна вказувати ім’я колонки, яка містить масиви (у нашому випадку це колонка product_ids):
SELECT array_length(column, 1)
FROM tableДізнатися більше про функції для роботи з масивами можна у документації. З деякими з них ми познайомимося далі.
Завдання 16.9
Порахуйте кількість замовлень у таблиці orders із дев’ятьма і більше товарами. Для цього скористайтесь функцією array_length, відфільтруйте дані щодо кількості товарів у замовленні та проведіть агрегацію. Отриманий стовпець назвіть orders.
Поле в результуючій таблиці: orders
Пояснення: у наших даних у колонці product_ids містяться звичайні списки товарів лише з однією розмірністю.
%%sql
SELECT count(order_id) as orders
FROM orders
WHERE array_length(product_ids, 1) >= 9| orders | |
|---|---|
| 0 | 5 |
AGEВ якості агрегатних функцій можуть виступати не тільки стовпці, але також розрахункові колонки або результат іншої функції:
SELECT AVG(some_function(column))
FROM table
SELECT AVG(column_1 + column_2)
FROM tableСпробуємо розрахувати середній вік користувачів чоловічої статі. Для цього скористаємось новою для нас функцією AGE.
Функція AGE повертає різницю між двома значеннями, наведеними у форматі TIMESTAMP. При цьому від першого значення віднімається друге, а сама різниця повертається у форматі INTERVAL:
SELECT AGE('2022-12-12', '2021-11-10')
Результат:
397 days, 0:00:00Таким чином, з '2021-11-10' до '2022-12-12' пройшло рівно 397 днів.
Якщо в якості першого аргументу нічого не вказати, то на місце першої дати автоматично підставиться поточна дата (опівніч поточного дня, тобто початок дня).
Якщо сьогодні '2022-12-12', то з '2021-11-10' пройшло рівно стільки ж днів, скільки у прикладі вище:
SELECT AGE(TIMESTAMP '2021-11-10')
Результат:
397 days, 0:00:00Насправді поточній даті відповідає значення current_date, яке можна вказувати як аргумент функції AGE:
SELECT AGE(TIMESTAMP '2021-11-10')
Результат:
397 days, 0:00:00Можете самостійно запустити два запити - з current_date і без - і порівняти отримані результати. У вашому випадку це будуть нові результати, але вони мають збігтися.
А саме значення current_date можна викликати так:
SELECT current_date
Результат:
2023-06-01 Для того щоб результат відображався не у кількості днів, а в зручнішому форматі, можна переводити результат обчислень у тип VARCHAR:
SELECT AGE(current_date, '2021-11-10')::VARCHAR
Результат:
1 year 1 mon 2 daysЗавдання 16.10
За допомогою функції AGE і агрегатної функції розрахуйте вік наймолодшого кур’єра чоловічої статі в таблиці couriers.
Вік виведіть через кількість років, місяців і днів (як у прикладі вище), перевівши їх у тип VARCHAR.
В якості дати, відносно якої необхідно розрахувати вік кур’єрів, використовуйте свою поточну дату (або не вказуйте її на місці першого аргументу, як показано в прикладах).
Отриману колонку зі значенням віку назвіть min_age.
Поле у результуючій таблиці: min_age
Пояснення: оскільки в якості дати, щодо якої проводиться розрахунок віку, ми використовуємо поточну дату, кожен новий день ми отримуватимемо новий результат.
Зрозуміло, що рахувати вік у такий спосіб не зовсім коректно. Ми навчимося робити це правильно в розділі «Підзапити».
%%sql
SELECT age(max(birth_date))::varchar as min_age
FROM couriers
WHERE sex = 'male'| min_age | |
|---|---|
| 0 | 17 years 8 months 28 days 13:03:18.214 |
CASE WHENАргументом агрегатної функції може бути і складніша розрахункова колонка - наприклад, отримана в результаті роботи конструкції CASE.
У такому випадку сама конструкція CASE поміщається всередину дужок агрегатної функції:
AVG(
CASE
WHEN logical_expression_1 THEN expression_1
WHEN logical_expression_2 THEN expression_2
ELSE expression_else
END
)Так, якби в нашій таблиці всі товари були розбиті за категоріями і ми захотіли б порахувати середню ціну товарів з урахуванням підвищувальних чи знижувальних коефіцієнтів для кожної категорії, то ми могли б зробити це, наприклад, так:
SELECT AVG(
CASE
WHEN category="м'ясо" THEN price*0.95
WHEN category="риба" THEN price*0.9
WHEN category="напої" THEN price*1.05
ELSE price
END
) AS avg_price
FROM productsДавайте ускладнимо одне з попередніх завдань і розрахуємо вартість ще одного замовлення.
Завдання 16.11
Порахуйте вартість замовлення, в якому будуть три пачки крекерів ('crackers'), дві пачки чіпсів ('chips') та один енергетичний напій ('energy drink'). Колонку із розрахованою вартістю замовлення назвіть order_price.
Для розрахунків використовуйте таблицю products.
Поле в результуючій таблиці: order_price
Для розв’язання задачі необхідно за допомогою конструкції CASE створити розрахункову колонку, в якій навпроти кожного товару, який увійшов у замовлення, проставити ціну, помножену на кількість таких товарів у замовленні. Для товарів, які не увійшли у замовлення, необхідно вказати ціну, що дорівнює 0 або NULL. Потім за допомогою агрегатної функції достатньо порахувати суму значень у новій розрахунковій колонці.
%%sql
SELECT sum(case when name = 'crackers' then price * 3
when name = 'chips' then price * 2
when name = 'energy drink' then price
else 0 end) as order_price
FROM products| order_price | |
|---|---|
| 0 | 355.0 |
Ми розглянули кілька прикладів, коли в якості агрументу агрегатних функцій виступає результат виконання іншої функції.
Але агрегатна функція може і сама опинитися на місці аргументу якоїсь функції:
SELECT some_function(SUM(column)) AS result
FROM tableНаочний приклад — застосування функції ROUND до результату агрегації:
SELECT ROUND(SUM(column)) AS rounded_sum
FROM tableДавайте вирішимо схоже завдання і заразом ненадовго повернемося до наших напоїв та оператора LIKE.
Завдання 16.12
Розрахуйте середню ціну товарів у таблиці products, у назвах яких є слова 'tea' чи 'coffee'. Виключіть з розрахунку товари, що містять «іван-чай» ('ivan-tea') або «чайний гриб» ('tea mushroom').
Середню ціну округліть до двох знаків після коми. Стовпець із отриманим значенням назвіть avg_price.
Поле у результуючій таблиці: avg_price
Пояснення: пам’ятайте, що виконання логічних виразів можна керувати за допомогою дужок. Це може стати в нагоді.
%%sql
SELECT round(avg(price), 2) as avg_price
FROM products
WHERE (name like '%tea%'
or name like '%coffee%')
and name not like '%ivan-tea%'
and name not like '%mushroom%'| avg_price | |
|---|---|
| 0 | 135.23 |
Втім, бувають і випадки, коли як аргументи деякої функції виступають відразу кілька агрегатних функцій:
SELECT some_function(SUM(column_1), SUM(column_2)) AS result
FROM tableНаприклад, нам уже знайома функція AGE, яка може приймати одразу два аргументи - дату кінця та дату початку деякого періоду часу.
Завдання 16.13
Скористайтеся функцією AGE та розрахуйте різницю у віці між найстарішим та наймолодшим користувачами чоловічої статі у таблиці users.
Різницю у віці висловіть кількістю років, місяців та днів, перевівши її у тип VARCHAR.
Назвіть колонку з порахованим значенням age_diff.
Поле у результуючій таблиці: age_diff
Це завдання можна вирішити різними способами: можна просто знайти різницю між датами народження наймолодшого і найстарішого користувачів, а можна порахувати різницю між їх віком. Можете піти будь-яким шляхом. Якщо рахуватимете вік, то в якості першої дати використовуйте свою поточну дату (current_date).
%%sql
SELECT age(max(birth_date), min(birth_date))::varchar as age_diff
FROM users
WHERE sex = 'male'| age_diff | |
|---|---|
| 0 | 21 years 9 months 27 days |
А тепер розглянемо приклад, коли агрегатна функція приймає в якості аргументу одну функцію і при цьому сама є аргументом іншої функції.
Виглядати це може так:
SELECT function_two(SUM(funtion_one(column))) AS result
FROM tableУ цьому прикладі спочатку до колонки column застосовується функція funtion_one, потім за допомогою функції SUM буде пораховано суму отриманих значень, і тільки потім до результату агрегації застосовується функція funtion_two.
Завдання 16.14
Розрахуйте середню кількість товарів у замовленнях з таблиці orders, які користувачі оформляли у вихідні дні (субота та неділя) протягом усього часу роботи сервісу.
Отримане значення округліть до двох знаків після коми. Назвіть колонку з ним avg_order_size.
Поле у результуючій таблиці: avg_order_size
Для розрахунку кількості товарів у замовленнях скористайтесь функцією array_length. Для фільтрації таблиці у вихідні дні можна використовувати функцію DATE_PART з параметром 'dow'.
%%sql
SELECT round(avg(array_length(product_ids, 1)), 2) as avg_order_size
FROM orders
WHERE date_part('dow', creation_time) in (6, 0)| avg_order_size | |
|---|---|
| 0 | 3.39 |
Результати декількох агрегатних функцій можна використовувати в одному запиті для проведення над ними арифметичних операцій:
SELECT (SUM(column_1) + SUM(column_2)) / 2
FROM tableУ запиті вище буде пораховано середнє арифметичне двох сум — значень колонки column_1 і значень колонки column_2.
Завдання 16.15
На основі даних у таблиці user_actions порахуйте: - кількість унікальних користувачів сервісу; - кількість унікальних замовлень - скільки замовлень припадає на одного користувача.
У результуючій таблиці відобразіть усі три значення – поля назвіть відповідно unique_users, unique_orders, orders_per_user.
Показник числа замовлень користувача округліть до двох знаків після коми.
Поля у результуючій таблиці: unique_users, unique_orders, orders_per_user
Щоб отримати коректний результат поділу, необхідно хоча б одне із значень попередньо привести до типу DECIMAL (або помножити на 1.0). Інакше результатом розподілу цілого числа інше ціле число буде теж ціле число.
До речі, з подібною проблемою можна ознайомитись на stackoverflow. Це дуже корисний ресурс для пошуку відповідей на свої запитання. Навіть досвідчені програмісти часто ним користуються. Можете вже зараз почати виробляти звичку звертатися до нього за необхідності.
Також пам’ятайте, що використовувати в розрахунках аліаси нових колонок не можна.
%%sql
SELECT count(distinct user_id) as unique_users,
count(distinct order_id) as unique_orders,
round(count(distinct order_id) * 1.0 / count(distinct user_id),
2) as orders_per_user
FROM user_actions
-- Рішення через DECIMAL
-- SELECT count(distinct user_id) as unique_users,
-- count(distinct order_id) as unique_orders,
-- round(count(distinct order_id)::DECIMAL / count(distinct user_id),
-- 2) as orders_per_user
-- FROM user_actions| unique_users | unique_orders | orders_per_user | |
|---|---|---|---|
| 0 | 21401 | 59595 | 2.78 |
І насамкінець познайомимося з більш просунутим функціоналом — агрегатними виразами з фільтрацією.
Якщо після агрегатної функції вказати ключове слово FILTER і помістити в дужках деяку умову condition після WHERE, то агрегатній функції на вхід будуть подані тільки ті рядки, для яких умова фільтра виявиться істинною.
Загалом ця конструкція виглядає так:
SELECT agg_function(column) FILTER (WHERE condition)
FROM tableНаприклад, якби ми захотіли порахувати середню ціну тільки для товарів категорії 'fish', то запит виглядав би так:
SELECT AVG(price) FILTER (WHERE category = 'fish') AS avg_fish_price
FROM tableЗверніть увагу: це дуже схоже на звичайну фільтрацію з агрегацією, яку ми розглядали в попередніх завданнях, тільки в даному випадку умова відбору записів вказується відразу в блоці SELECT.
Перевага такого запису в тому, що він дозволяє проводити розрахунки без проміжних запитів з умовами у блоці WHERE.
Розглянемо ще один приклад.
У нашому випадку досить зрозуміло, як порахувати загальну кількість користувачів. Також зрозуміло, як порахувати кількість користувачів, які хоча б раз скасовували замовлення — досить просто вказати потрібну умову в операторі WHERE. Але як у рамках одного запиту порахувати тих, хто ніколи не скасовував своє замовлення?
Оскільки об’єднувати кілька запитів разом ми поки що не вміємо, нам допоможе прийти агрегатний вираз.
Завдання 16.16
Порахуйте скільки користувачів ніколи не скасовували своє замовлення. Для цього із загальної кількості всіх унікальних користувачів відніміть кількість унікальних користувачів, які хоча б раз скасовували замовлення. Подумайте, яку умову необхідно вказати у FILTER, щоб отримати коректний результат.
Отриманий стовпець назвіть users_count.
Поле в результуючій таблиці: users_count
%%sql
-- Рішення через різницю
SELECT count(distinct user_id) - count(distinct user_id) filter (WHERE action = 'cancel_order') as users_count
FROM user_actions
-- Рішення через вкладений запит
-- SELECT count(distinct user_id) filter (WHERE user_id not in (SELECT DISTINCT user_id
-- FROM user_actions
-- WHERE action = 'cancel_order')) as users_count
-- FROM user_actions| users_count |
|---|
Давайте вирішимо ще одне завдання на агрегатні вирази з фільтрацією - цього разу з більш складними розрахунками.
Завдання 16.17
Порахуйте:
ordersУ результуючій таблиці відобразіть усі три значення - поля назвіть відповідно orders, large_orders, large_orders_share.
Частку замовлень із п’ятьма та більше товарами у загальній кількості товарів округліть до двох знаків після коми.
Поля в результуючій таблиці: orders, large_orders, large_orders_share
Пояснення: при розрахунку частки не забудьте хоча б одне із значень попередньо привести до типу DECIMAL (або домножити на 1.0). Також пам’ятайте, що використовувати в розрахунках аліаси нових колонок не можна.
%%sql
SELECT count(distinct order_id) as orders,
count(distinct order_id) filter (WHERE array_length(product_ids, 1) >= 5) as large_orders,
round(count(distinct order_id) filter (WHERE array_length(product_ids, 1) >= 5)::decimal / count(distinct order_id),
2) as large_orders_share
FROM orders| orders | large_orders | large_orders_share | |
|---|---|---|---|
| 0 | 59595 | 11498 | 0.19 |