🔥 Cекреты функции sorted() в Python
Итак, в Python существует функция
Для сортировки списка объектов по одному из их атрибутов, как раз можем использовать функцию
🟧 Например, у нас есть список клиентов с разными атрибутами, у каждого - имя, возраст и доход:
>> Ключ сортировки - это функция, которая принимает каждый элемент массива и возвращает значение, по которому будет производиться сортировка.
🟨 В нашем случае мы будем использовать лямбда-функцию, которая возвращает значение атрибута
Итак, используем лямбда-функцию, чтобы указать ключ сортировки. Она вернет значение
Таким образом, функция
#python
Итак, в Python существует функция
sorted(), которая используется для сортировки данныx. sorted() упорядочивает данные таким образом, чтобы было легче провести анализ и извлечь нужную информацию. Например, в аналитике, сортировка клиентов по возрасту, территориальной принадлежности и другим критериям - далеко не редкая задача.Для сортировки списка объектов по одному из их атрибутов, как раз можем использовать функцию
sorted() в Python. Она отсортирует любой итерируемый объект: список, кортеж или множество.🟧 Например, у нас есть список клиентов с разными атрибутами, у каждого - имя, возраст и доход:
client_list = [И мы хотим отсортировать этот список по возрастанию возраста. Мы не получим нужный результат если просто передадим наш список в
{'name': 'John', 'age': 25, 'income': 50000},
{'name': 'Mary', 'age': 30, 'income': 70000},
{'name': 'Bob', 'age': 35, 'income': 40000},
{'name': 'Alice', 'age': 27, 'income': 60000}
]
sorted(). Нужно дополнительно указать ключ сортировки.>> Ключ сортировки - это функция, которая принимает каждый элемент массива и возвращает значение, по которому будет производиться сортировка.
🟨 В нашем случае мы будем использовать лямбда-функцию, которая возвращает значение атрибута
'age' или 'income' каждого клиента в списке. Мы напишем key=lambda x: x['age'], чтобы указать, что мы хотим отсортировать список по возрастанию возраста клиентов. Если понадобится отсортировать список по другому атрибуту, то мы поменяем ключ на key=lambda x: x['нужный атрибут'].Итак, используем лямбда-функцию, чтобы указать ключ сортировки. Она вернет значение
'age' для каждого клиента в списке:sorted(client_list, key=lambda x: x['age'])🟦 Аналогично, если вы хотите отсортировать список клиентов по убыванию их доходов - добавьте параметр reverse=True:
sorted(client_list, key=lambda x: x['income'], reverse=True)🟪 Абсолютно таким же образом с помощью
sorted() мы сможем отсортировать список объектов класса по некоторому атрибуту. Нам просто понадобится передать в key нужный нам атрибут: key=lambda x: x.age.Таким образом, функция
sorted() сокращает время на написание дополнительного кода и этим облегчает работу.#python
🔥18👍5❤2
🔥 Считаем скользящее среднее в PostgreSQL
Расчет скользящего среднего - один из наиболее распространенных методов анализа временных рядов. В PostgreSQL для решения этой задачи можно и нужно использовать оконные функции.
🟡 Для примера, допустим у нас есть таблица
Данный параметр определяет рамки (окно) для выполнения оконных функций. В частности, он указывает, какие строки будут включены в вычисление агрегирующей функции.
Например, в выражении ROWS BETWEEN 2 PRECEDING AND CURRENT ROW используется два ключевых слова - PRECEDING и CURRENT. Ключевое слово
Таким образом,
Этот параметр может быть любым, например:
-
-
-
🟢 Вот так просто использование оконных функций позволяет рассчитывать скользящее среднее и другие агрегирующие функции без создания временных таблиц. Главное, знать что и как использовать 🙂
#sql
Расчет скользящего среднего - один из наиболее распространенных методов анализа временных рядов. В PostgreSQL для решения этой задачи можно и нужно использовать оконные функции.
🟡 Для примера, допустим у нас есть таблица
sales с данными о продажах за определенный период времени:date | amountЧтобы посчитать скользящее среднее за последние три дня, удобнее всего использовать оконную функцию
------------+-------
2022-01-01 | 100
2022-01-02 | 200
2022-01-03 | 150
2022-01-04 | 50
2022-01-05 | 300
AVG(), указав определенный диапазон строк (ROWS BETWEEN 2 PRECEDING AND CURRENT ROW):SELECTВ результате получим таблицу, где для каждой строки будет рассчитано значение скользящего среднего за последние три дня:
date,
amount,
AVG(amount) OVER (
ORDER BY date
ROWS BETWEEN 2 PRECEDING
AND CURRENT ROW
) AS avg
FROM sales;
date | amount | avg🔵 Давайте разберем более подробно выражение
------------+--------+--------
2022-01-01 | 100 | 100.00
2022-01-02 | 200 | 150.00
2022-01-03 | 150 | 150.00
2022-01-04 | 50 | 133.33
2022-01-05 | 300 | 166.67
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW. Эта конструкция часто вызывает вопросы.Данный параметр определяет рамки (окно) для выполнения оконных функций. В частности, он указывает, какие строки будут включены в вычисление агрегирующей функции.
Например, в выражении ROWS BETWEEN 2 PRECEDING AND CURRENT ROW используется два ключевых слова - PRECEDING и CURRENT. Ключевое слово
CURRENT определяет текущую строку, а PRECEDING - N предшествующих строк. Существует еще FOLLOWING, что означает - следующие строки.Таким образом,
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW означает, что в окно будет включена текущая строка и две предыдущие строки.Этот параметр может быть любым, например:
-
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW - включить все строки от начала таблицы до текущей строки-
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING - включить текущую строку и ее соседние строки-
RANGE BETWEEN '1 day' PRECEDING AND '1 day' FOLLOWING - включить все строки, которые находятся в интервале от одного дня до другого🟢 Вот так просто использование оконных функций позволяет рассчитывать скользящее среднее и другие агрегирующие функции без создания временных таблиц. Главное, знать что и как использовать 🙂
#sql
👍23🔥8😱2❤1
🔥 Чек-лист по созданию гипотез
🎓 Недавно наш студент поделился интересными мыслями о том, как создавать качественные гипотезы. И знаете что? Он был настолько крут, что мы решили поделиться его идеями с вами.
Хотите узнать, какой должна быть гипотеза? Тогда читайте дальше!
✅ Первый и самый важный критерий хорошей гипотезы - ее проверяемость. Гипотеза должна быть сформулирована таким образом, чтобы провести эксперимент и получить результаты, которые подтвердят или опровергнут ее.
Например, "Пиар влияет на продажи" или "У компании должен быть солидный сайт" - никак не гипотезы. Без проверки они останутся домыслами.
✅ Второй критерий - влияние на метрики. Хорошая гипотеза должна влиять на какую-то метрику. Это значит, что мы можем понять, подтвердилась ли она или нет, изменилась ли метрика в ходе эксперимента.
Например, "Сделаем рассылку по базе с акцией" - плохая гипотеза, а "Если сделаем рассылку, получим 10 лидов" - хорошая гипотеза.
✅ Рискованность. Хорошая гипотеза должна быть неочевидной и рискованной. Чем более неожиданным будет результат, тем больше шансов на успех.
Например, "Если мы уже знаем, что с рассылки будет 10 лидов", то это не гипотеза, а факт.
✅ Быстрота проверки. Хорошая гипотеза должна быть проверяема за короткий период времени. Если эксперимент займет слишком много времени, мы потратим слишком много ресурсов, а результаты могут потерять свою актуальность.
Например, "Давайте за полгода переделаем сайт, чтобы конверсия выросла на 2 процентных пункта" - плохая гипотеза, а "Давайте изменим оффер на сайте за 1 час, чтобы конверсия выросла на 0.2 процентных пункта за неделю" - хорошая гипотеза.
✅ Дешевизна. Если проверка гипотезы стоит слишком дорого, то это может оказаться неэффективным для бизнеса. Поэтому лучше делать ставку на более дешевые эксперименты и быстрые результаты.
Например, если вы хотите сделать мобильное приложение за 1.5 млн.рублей, чтобы понять, будут ли востребованы цифровые стилисты - это плохая гипотеза. Если же за 5 тысяч рублей, а лучше бесплатно, соберете лендинг на Тильде, чтобы проверить, то это - хорошая гипотеза.
✅ Реалистичность. Хорошая гипотеза должна быть реалистичной, то есть у нас должны быть ресурсы на ее проверку (время, деньги, люди). Мы должны убедиться, что мы можем провести эксперимент, иначе гипотеза будет бессмысленной. Поэтому перед формулированием гипотезы необходимо оценить свои ресурсы и возможности проведения эксперимента.
❗️ Эти советы точно помогут вам лучше понимать формирование гипотез и стать настоящими мастерами. Ведь проверка гипотез - это ключевой инструмент для роста бизнеса, а значит, и вашей карьеры. И пусть каждый эксперимент приближает вас к вашим целям!
📈 На Симуляторе "Аналитик данных" мы особое внимание уделяем способам расчета и пониманию продуктовых метрик, проверке гипотез и проведению A/B тестов. Попробуйте демо-главу!
#analytics #продуктовые_метрики
🎓 Недавно наш студент поделился интересными мыслями о том, как создавать качественные гипотезы. И знаете что? Он был настолько крут, что мы решили поделиться его идеями с вами.
Хотите узнать, какой должна быть гипотеза? Тогда читайте дальше!
✅ Первый и самый важный критерий хорошей гипотезы - ее проверяемость. Гипотеза должна быть сформулирована таким образом, чтобы провести эксперимент и получить результаты, которые подтвердят или опровергнут ее.
Например, "Пиар влияет на продажи" или "У компании должен быть солидный сайт" - никак не гипотезы. Без проверки они останутся домыслами.
✅ Второй критерий - влияние на метрики. Хорошая гипотеза должна влиять на какую-то метрику. Это значит, что мы можем понять, подтвердилась ли она или нет, изменилась ли метрика в ходе эксперимента.
Например, "Сделаем рассылку по базе с акцией" - плохая гипотеза, а "Если сделаем рассылку, получим 10 лидов" - хорошая гипотеза.
✅ Рискованность. Хорошая гипотеза должна быть неочевидной и рискованной. Чем более неожиданным будет результат, тем больше шансов на успех.
Например, "Если мы уже знаем, что с рассылки будет 10 лидов", то это не гипотеза, а факт.
✅ Быстрота проверки. Хорошая гипотеза должна быть проверяема за короткий период времени. Если эксперимент займет слишком много времени, мы потратим слишком много ресурсов, а результаты могут потерять свою актуальность.
Например, "Давайте за полгода переделаем сайт, чтобы конверсия выросла на 2 процентных пункта" - плохая гипотеза, а "Давайте изменим оффер на сайте за 1 час, чтобы конверсия выросла на 0.2 процентных пункта за неделю" - хорошая гипотеза.
✅ Дешевизна. Если проверка гипотезы стоит слишком дорого, то это может оказаться неэффективным для бизнеса. Поэтому лучше делать ставку на более дешевые эксперименты и быстрые результаты.
Например, если вы хотите сделать мобильное приложение за 1.5 млн.рублей, чтобы понять, будут ли востребованы цифровые стилисты - это плохая гипотеза. Если же за 5 тысяч рублей, а лучше бесплатно, соберете лендинг на Тильде, чтобы проверить, то это - хорошая гипотеза.
✅ Реалистичность. Хорошая гипотеза должна быть реалистичной, то есть у нас должны быть ресурсы на ее проверку (время, деньги, люди). Мы должны убедиться, что мы можем провести эксперимент, иначе гипотеза будет бессмысленной. Поэтому перед формулированием гипотезы необходимо оценить свои ресурсы и возможности проведения эксперимента.
❗️ Эти советы точно помогут вам лучше понимать формирование гипотез и стать настоящими мастерами. Ведь проверка гипотез - это ключевой инструмент для роста бизнеса, а значит, и вашей карьеры. И пусть каждый эксперимент приближает вас к вашим целям!
📈 На Симуляторе "Аналитик данных" мы особое внимание уделяем способам расчета и пониманию продуктовых метрик, проверке гипотез и проведению A/B тестов. Попробуйте демо-главу!
#analytics #продуктовые_метрики
🔥15👍4👎1
🔥 Апгрейдим Pandas: создаем условные столбцы без лишних циклов
Кто работал с большими объемами данных в Pandas, наверняка знает, что обработать столбцы по условию может оказаться довольно затратной операцией. Мы часто слышим: используйте векторизацию! А что это, где это найти? Объясняем.
> Векторизация - это способ обработки данных, при котором операции применяются не поочередно к каждому элементу массива, а сразу ко всему массиву. Многие методы pandas, в общем говоря, уже векторизованы и вам не нужно об этом задумываться, НО!
❓ Каким методом вы бы воспользовались для фильтрации столбца по условию?
🔵 Самый распространенный способ
Очень часто для этого используют
Тем не менее
💡 Давайте покажем вам как можно создать условный столбец более эффективно - векторизованным способом:
Для начала создадим DataFrame с 10 миллионами случайных чисел от 0 до 1:
🟢 Более удобный способ
Выход из ситуации -
Базовый синтаксис:
Condition - условие; если оно выполняется то будут выбраны элементы из x; в противном случае - если это
🟣 Так что, если хотите обработать большие объемы данных в Pandas быстро и без лишних циклов, однозначно используйте
#python #pandas #numpy
Кто работал с большими объемами данных в Pandas, наверняка знает, что обработать столбцы по условию может оказаться довольно затратной операцией. Мы часто слышим: используйте векторизацию! А что это, где это найти? Объясняем.
> Векторизация - это способ обработки данных, при котором операции применяются не поочередно к каждому элементу массива, а сразу ко всему массиву. Многие методы pandas, в общем говоря, уже векторизованы и вам не нужно об этом задумываться, НО!
❓ Каким методом вы бы воспользовались для фильтрации столбца по условию?
🔵 Самый распространенный способ
Очень часто для этого используют
apply(), да и не только для фильтрации, а и для применения какой-либо функции к столбцу. Очень нужный и полезный метод, иногда незаменимый.Тем не менее
apply() - это не что иное, как усовершенствованный цикл. И из-за этого теряется вся суть векторизации.💡 Давайте покажем вам как можно создать условный столбец более эффективно - векторизованным способом:
Для начала создадим DataFrame с 10 миллионами случайных чисел от 0 до 1:
import pandas as pd🔴 Сразу посмотрим как поведет себя
import numpy as np
df = pd.DataFrame(np.random.random((10**7,1)).round(2), columns = ['col1'])
apply(). Определим функцию, которая для каждого числа будет возвращать 'Class A', если число больше 0.5, и 'Class B' в противном случае:def assign_class(num):Передадим её в
if num > 0.5:
return 'Class A'
return 'Class B'
apply() и замерим время:%timeit a = df.col1.apply(assign_class)И чем больше будут данные, тем более печальным будет время. ☹️
# 1.96 s ± 302 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
🟢 Более удобный способ
Выход из ситуации -
np.where(). Он позволяет обрабатывать все гораздо быстрее, как раз являясь одним из многих инструментов векторизации:%timeit a = np.where(df['col1']>0.5, 'Class A', 'Class B')Существенное преимущество налицо!
# 282 ms ± 14.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Базовый синтаксис:
numpy.where(condition [, x, y]). Condition - условие; если оно выполняется то будут выбраны элементы из x; в противном случае - если это
false, будут взяты элементы из y.🟣 Так что, если хотите обработать большие объемы данных в Pandas быстро и без лишних циклов, однозначно используйте
np.where(). А мы, со своей стороны cделаем все возможное, чтобы с такими инструментами вас знакомить: в Симуляторе “Аналитик данных” в модуле Python мы 2 главы уделяем самым популярным библиотекам Python: Pandas и Numpy!#python #pandas #numpy
🔥20👍5
🚀 Быстрый лайфхак для всех Юпитер-юзеров!
Признавайтесь все, кто работает с
Всё бы наверное ничего, но как быть, когда вам срочно нужен определенный код из неизвестно какого ноутбука? Ох и работа вам предстоит в таком случае!
🟢 Но у нас есть маленький хитрый способ, который поможет сэкономить кучу времени и уберечь от ручного поиска!
Попробуем? Для начала запустите следующую команду в терминале:
Так вот мы к чему, старайтесь давать вашим ноутбукам осмысленные имена. Конечно у всех были беззаботные времена с 3 ноутбуками, в которых не запутаться, но изначально такая стратегия губительна!
Но если уже завал - вы знаете чем пользоваться для поиска бриллиантов в недрах ваших блокнотов! 😉
#лайфхак
Признавайтесь все, кто работает с
Jupyter Notebook, всегда ли у ваших ноутбуков осмысленные имена? Или у вас тоже есть огромная стопка блокнотов "Без названия"?Всё бы наверное ничего, но как быть, когда вам срочно нужен определенный код из неизвестно какого ноутбука? Ох и работа вам предстоит в таком случае!
🟢 Но у нас есть маленький хитрый способ, который поможет сэкономить кучу времени и уберечь от ручного поиска!
nbcommands - набор инструментов, предоставляющий команды для взаимодействия с ноутбуками прямо из терминала. С помощью nbcommands можно быстро искать код, просматривать ячейки, объединять блокноты и многое другое.Попробуем? Для начала запустите следующую команду в терминале:
!pip install nbcommands
А затем используйте nbgrep для поиска конкретного кода по всем вашим Jupyter Notebook:nbgrep "import pandas" ./
./ означает: ищем по всем ноутбукам текущей директории, а "import pandas" - строка, которую ищем. Также можно передать имя определенного ноутбука и искать только в нем, например: nbgrep "import pandas" notebook.ipynb
🟣 Кроме того, nbcommands также предоставляет несколько интересных команд: быстрый просмотр первых или последних ячеек в ноутбуке, объединение ноутбуков и другие. Планируются и новые улучшения, например: поиск различий в двух ноутбуках и интерактивное редактирование.Так вот мы к чему, старайтесь давать вашим ноутбукам осмысленные имена. Конечно у всех были беззаботные времена с 3 ноутбуками, в которых не запутаться, но изначально такая стратегия губительна!
Но если уже завал - вы знаете чем пользоваться для поиска бриллиантов в недрах ваших блокнотов! 😉
#лайфхак
🔥22👍5
🔥 Оператор ROLLUP в PostgreSQL
Одним из самых основных операторов в любом диалекте SQL является
Но в аналитике часто требуется посмотреть на статистические показатели в разных «разрезах». Например, для анализа продаж интересно узнать сколько товаров продано по каждому бренду и сегменту, а также общее количество. Такой, промежуточный итог. Думаете мы будем рассказывать об Excel? Могли бы, но нет! 🙃
Мы расскажем о достаточно редко используемой, но очень полезной вещи в PostgreSQL -
🟢 Посмотрим на примерах
Допустим, нам необходимо получить общую сумму товаров, а также сумму проданных по каждому бренду и сегменту. Мы можем написать следующий запрос:
При использовании
❗️Причем обратите внимание на иерархию: сначала brand, потом segment.
Мы можем их и поменять:
Теперь, когда вы уже немного представляете о чем речь, давайте посмотрим на синтаксис:
Например, для
- c1, c2, c3;
- c1, c2;
- c1;
- все строки выборки.
📅 ROLLUP с датами
Довольно часто
#sql
Одним из самых основных операторов в любом диалекте SQL является
GROUP BY. Любой, кто часто взаимодействует с базами данных, наверняка использовал его тысячи раз для подсчета всевозможных агрегаций (сумм, средних значений и тд).Но в аналитике часто требуется посмотреть на статистические показатели в разных «разрезах». Например, для анализа продаж интересно узнать сколько товаров продано по каждому бренду и сегменту, а также общее количество. Такой, промежуточный итог. Думаете мы будем рассказывать об Excel? Могли бы, но нет! 🙃
Мы расскажем о достаточно редко используемой, но очень полезной вещи в PostgreSQL -
ROLLUP. Это в некоторым смысле часть GROUP BY, которая формирует промежуточные итоги для каждого указанного элемента и общий итог.🟢 Посмотрим на примерах
Допустим, нам необходимо получить общую сумму товаров, а также сумму проданных по каждому бренду и сегменту. Мы можем написать следующий запрос:
SELECTРезультаты запросов смотрите в карточках под постом.
brand,
segment,
SUM(quantity)
FROM
sales
GROUP BY
ROLLUP (
brand, segment)
ORDER BY
brand,
segment;
При использовании
ROLLUP строки со значениями NULL и будут промежуточными итогами, а последняя строка - общим итогом.❗️Причем обратите внимание на иерархию: сначала brand, потом segment.
Мы можем их и поменять:
SELECT🔵 Синтаксис
segment,
brand,
SUM(quantity)
FROM
sales
GROUP BY
ROLLUP (
segment, brand)
ORDER BY
segment,
brand;
Теперь, когда вы уже немного представляете о чем речь, давайте посмотрим на синтаксис:
SELECTДанные из
c1,
c2,
c3,
aggregate(c4)
FROM
table_name
GROUP BY
ROLLUP (
c1, c2, c3);
FROM и WHERE группируются отдельно для каждого заданного набора группировки. Затем для каждой группы вычисляются агрегатные функции, как и при использовании простого GROUP BY, а в конце результаты объединяются.Например, для
GROUP BY ROLLUP(c1, c2, c3) результатом запроса будет объединение результатов GROUP BY по:- c1, c2, c3;
- c1, c2;
- c1;
- все строки выборки.
📅 ROLLUP с датами
Довольно часто
ROLLUP используют с датами, давайте посмотрим на такой пример, чтобы закрепить:SELECT🟣 На самом деле,
EXTRACT(YEAR FROM rental_date) y,
EXTRACT(MONTH FROM rental_date) M,
EXTRACT(DAY FROM rental_date) d,
COUNT(rental_id)
FROM
rental
GROUP BY
ROLLUP (
EXTRACT(YEAR FROM rental_date),
EXTRACT(MONTH FROM rental_date),
EXTRACT(DAY FROM rental_date)
);
ROLLUP редко встретишь в обучениях или статьях - довольно специфическая вещь. Но она позволяет агрегировать не только по столбцам, но и по подгруппам и по определенным наборам управлять иерархией. Формируя такие запросы мы можем куда подробнее видеть взаимосвязь данных и их комбинации, что дает нам большее понимание происходящего.#sql
🔥21👍5
🔥 Нестандартная ситуация со словарями
Мы знаем, что вы - любите Python, а еще больше любите необычные фишки. Но знали ли вы, что при работе со словарями могут возникать довольно не интуитивные ситуации?
❓ Посмотрите, чему будет равен
✅ Мы знаем, что ключи должны быть уникальными и неизменяемыми. В данном случае нет никаких сомнений в том, что
📎 Но обратите еще внимание на итоговые ключ и значение:
❓Как так получилось?
Дело в том, что сначала
Наконец, при добавлении
❓А почему сохранен строковый ключ
Тут все просто: он имеет уникальное хеш-значение, отличное от других ключей.
💥 Надеемся, что этот пост дал вам чуть более полное понимание работы словарей. Приходите к нам на Симулятор "Аналитик данных", где мы с нуля обучаем SQL и Python и делимся полезными фишками!
#python
Мы знаем, что вы - любите Python, а еще больше любите необычные фишки. Но знали ли вы, что при работе со словарями могут возникать довольно не интуитивные ситуации?
❓ Посмотрите, чему будет равен
my_dict?my_dict = {
1.0: 'One (float)',
1: 'One (int)',
True: 'One (bool)',
'1': 'One (string)'
}
# {1.0: 'One (bool)', '1': 'One (string)'}
Несмотря на добавление 4 отдельных ключей в словарь, можете ли вы объяснить, почему он оставляет только два из них?✅ Мы знаем, что ключи должны быть уникальными и неизменяемыми. В данном случае нет никаких сомнений в том, что
1.0, 1 и True имеют разные типы данных.type(1.0), type(1), type(True)Если посмотреть на их
# (float, int, bool)
id, убедимся что и они различны:id(1.0), id(1), id(True)❌ Но дело не только в этом! Ключи должны быть еще хешируемы. Для поиска ключа, Python использует именно его хэш-значение, а не id. Значит посмотрим на их хэш-значения:
# (139644507527152, 139645051222320, 9758592)
hash(1.0), hash(1), hash(True)Вот и получается, поскольку они имеют одно и то же хэш-значение, словарь рассматривает их как одни и те же ключи.
# (1, 1, 1)
📎 Но обратите еще внимание на итоговые ключ и значение:
ключ - 1.0, в то время как значение соответствует ключу True.❓Как так получилось?
Дело в том, что сначала
1.0 добавляется в качестве ключа, а значение устанавливается 'One (float)'. Затем, добавляя ключ 1, python распознает его как эквивалентное хэш-значение. И значение, соответствующее 1.0, перезаписывается на 'One (int)', в то время как ключ (1.0) сохраняется как есть.Наконец, при добавлении
True снова получаем эквивалентность хэша с существующим ключом 1.0. И снова, значение, которое изначально было 'One (float)' и обновлено до 'One (int)' на предыдущем шаге, перезаписывается на 'One (bool)'.❓А почему сохранен строковый ключ
'1'? Тут все просто: он имеет уникальное хеш-значение, отличное от других ключей.
💥 Надеемся, что этот пост дал вам чуть более полное понимание работы словарей. Приходите к нам на Симулятор "Аналитик данных", где мы с нуля обучаем SQL и Python и делимся полезными фишками!
#python
🔥20👍6
💥 А вы знакомы с оператором MERGE в PostgreSQL?
На одном из собеседований нашего студента спросили "что делает оператор MERGE?". И хотя это, прямо скажем, не первая по важности вещь для аналитика, все-таки может быть полезна.
🟣 Так что же такое MERGE?
Представьте, что у вас есть таблица с инвентарем товаров, которые продает ваша компания. Время от времени вы получаете наборы данных либо с новыми продуктами, которые необходимо внести, либо списки товаров в наличии, которые могут иметь или не иметь расхождения с инвентарем.
Обычно такое обновление можно выполнить в стороннем приложении. Проблема только в перетаскивании данных туда-сюда, которые вероятно придется сделать несколько раз (из базы в приложение, и обратно), а это много дополнительных издержек (в данном случае времени).
🖋 Но с недавнего времени в этом нет необходимости, благодаря
Для работы с
🔵 Как это работает?
Начнем с двух таблиц и одной строки данных.
Указанная в запросе логика будет выполнена, и значение столбца x увеличится с 1 до 2.
И, каждый раз, когда мы перезапускаем запрос с
🟡 Можем и удалить!
Мы можем не только обновлять (
Теперь вы точно знаете, что ответить на собеседовании, и что
#sql #interview_problems
На одном из собеседований нашего студента спросили "что делает оператор MERGE?". И хотя это, прямо скажем, не первая по важности вещь для аналитика, все-таки может быть полезна.
🟣 Так что же такое MERGE?
MERGE - оператор, который заменяет сразу несколько других. Представьте, что у вас есть таблица с инвентарем товаров, которые продает ваша компания. Время от времени вы получаете наборы данных либо с новыми продуктами, которые необходимо внести, либо списки товаров в наличии, которые могут иметь или не иметь расхождения с инвентарем.
Обычно такое обновление можно выполнить в стороннем приложении. Проблема только в перетаскивании данных туда-сюда, которые вероятно придется сделать несколько раз (из базы в приложение, и обратно), а это много дополнительных издержек (в данном случае времени).
🖋 Но с недавнего времени в этом нет необходимости, благодаря
MERGE все можно легко сделать прямо в базе. Для работы с
MERGE нужны две таблицы. Таблица с обновлениями и основное хранилище данных - целевая таблица. Содержимое таблицы с обновлениями сравнивается с целевой, и в целевой таблице происходят изменения.🔵 Как это работает?
Начнем с двух таблиц и одной строки данных.
create table a (id int, x int, status char(10));Теперь мы можем попробовать
create table b (id int, x int, status char(10));
insert into a (id, x, status) values (1, 1, 'From a');
select * from a;
select * from b;
id | x | status
---+---+------------
1 | 1 | From a
(1 row)
id | x | status
---+---+--------
(0 rows)
MERGE в запросе. Таблица a содержит одну строку, а в таблице b - строк вообще нет. И в запросе записи, не включенные в целевую таблицу, мы вставляем, а те, которые есть, обновляем:MERGE into b using a on a.id = b.idЗапрос сообщает - сопоставь две таблицы по
when matched then
update set x = b.x + 1
when not matched then
insert (id, x, status) values (a.id, a.x, a.status);
id. Если есть строки, которые совпадают, то столбец x в таблице b увеличь на единицу. Но если совпадений нет (совпадения не будет, так как таблица b пуста), то содержимое строки из таблицы a копируется в таблицу b. Если мы теперь посмотрим на обе таблицы, мы увидим, что они идентичны. select * from a;🟢 А что если запустить MERGE снова?
select * from b;
id | x | status
----+---+------------
1 | 1 | From a
(1 row)
id | x | status
----+---+------------
1 | 1 | From a
(1 row)
Указанная в запросе логика будет выполнена, и значение столбца x увеличится с 1 до 2.
select * from a;
select * from b;
id | x | status
---+---+------------
1 | 1 | From a
(1 row)
id | x | status
---+---+------------
1 | 2 | From a
(1 row)
И, каждый раз, когда мы перезапускаем запрос с
MERGE - x будет увеличиваться.🟡 Можем и удалить!
Мы можем не только обновлять (
UPDATE) значения, но и удалять их. Например, давайте изменим наш запрос так, чтобы не увеличивать значение, а удалять строку в целевой таблице, если найдутся соответствующие строки.merge into b using a on a.id = b.idПримечание: операция
when matched then delete
when not matched then
insert (id, x, status) values (a.id, a.x, a.status);
select * from b;
id | x | status
----+---+--------
(0 rows)
MERGE доступна только в PostgreSQL 9.5 и более поздних версиях.Теперь вы точно знаете, что ответить на собеседовании, и что
MERGE чрезвычайно полезный инструмент. И даже эти очень простые примеры дают представление о его использовании. Во многих ситуациях ранее приходилось бы использовать множество дополнительных конструкций для такого обновления, а теперь достаточно знать один MERGE.#sql #interview_problems
🔥18👍6
🔥 Продуктовая метрика LIFETIME
Периодически мы все принимаем волевые решения «с понедельника» освоить новый навык или что-то изменить, например, изучать новый язык или ходить в зал. Некоторые попробуют пару дней и бросят, другие могут остаться в этой затее на несколько месяцев, но в итоге потерять интерес, в то время как единицы продолжат практиковаться долгие годы.
И ситуация с любым продуктом точно такая же - большинство людей перестанут им пользоваться, как только пропадет интерес или потребность, в то время как некоторые будут пользоваться им годами.
Это как раз показатель востребованности продукта, заинтересованности юзеров и, более того, «гарантия» их финансовой активности. И этот показатель -
Важно: мы не рассматриваем, контактировал ли пользователь с продуктом каждый день, но рассматриваем общее количество дней (с первого до последнего контакта), проведенных с продуктом.
Как считать?
Обычно
Есть несколько способов расчета
🟢 Наиболее точный способ
Берем группу пользователей, ждем пока все они полностью «отвалятся», и считаем среднее количество времени, которое они провели с нами до ухода.
Например, у нас есть когорта из 100 пользователей, и мы знаем, сколько дней они провели в проекте прежде, чем покинули его:
| Число клиентов | Кол-во дней |
| 30 | 1 |
| 20 | 7 |
| 10 | 14 |
| 10 | 18 |
| 10 | 22 |
| 5 | 31 |
| 5 | 40 |
| 5 | 45 |
| 5 | 54 |
В этом случае их
❓ Но, чувствуете подвох? Расчет точного
Поэтому обычно мы, грубо говоря, оцениваем
🟡 Второй способ
Одним из способов оценить
🟣 Третий способ
Другой способ - вычисление интеграла от
Что нам дает lifetime?
Важно иметь в виду, что
Вот поэтому он очень полезен - он дает общую картину продукта всего одним числом.
При работе с
Разница между Lifetime и Lifetime Value
Мы не раз видели подобные вопросы от наших студентов. Тут важно понимать, что
💥 Более подробно обсуждаем продуктовые метрики: какие бывают, как считать, где применять, как анализировать на нашем Симуляторе «Аналитик данных»!
#analytics #продуктовые_метрики
Периодически мы все принимаем волевые решения «с понедельника» освоить новый навык или что-то изменить, например, изучать новый язык или ходить в зал. Некоторые попробуют пару дней и бросят, другие могут остаться в этой затее на несколько месяцев, но в итоге потерять интерес, в то время как единицы продолжат практиковаться долгие годы.
И ситуация с любым продуктом точно такая же - большинство людей перестанут им пользоваться, как только пропадет интерес или потребность, в то время как некоторые будут пользоваться им годами.
Это как раз показатель востребованности продукта, заинтересованности юзеров и, более того, «гарантия» их финансовой активности. И этот показатель -
Lifetime.Lifetime - это среднее время, в течение которого пользователь остается активным. Важно: мы не рассматриваем, контактировал ли пользователь с продуктом каждый день, но рассматриваем общее количество дней (с первого до последнего контакта), проведенных с продуктом.
Как считать?
Обычно
lifetime считается по когортам, и чем больше времени проходит с первого контакта, тем меньше пользователей из когорты продолжают использовать продукт. А самый большой отток обычно происходит в первые дни (см. картинку под постом). Есть несколько способов расчета
lifetime. 🟢 Наиболее точный способ
Берем группу пользователей, ждем пока все они полностью «отвалятся», и считаем среднее количество времени, которое они провели с нами до ухода.
Например, у нас есть когорта из 100 пользователей, и мы знаем, сколько дней они провели в проекте прежде, чем покинули его:
| Число клиентов | Кол-во дней |
| 30 | 1 |
| 20 | 7 |
| 10 | 14 |
| 10 | 18 |
| 10 | 22 |
| 5 | 31 |
| 5 | 40 |
| 5 | 45 |
| 5 | 54 |
В этом случае их
lifetime равен 15,6 дням.❓ Но, чувствуете подвох? Расчет точного
lifetime может занять достаточно много времени и это почти невозможно в реальной жизни, поскольку придется ждать, пока все пользователи окончательно прекратят использовать продукт.Поэтому обычно мы, грубо говоря, оцениваем
lifetime, а не считаем его. И при оценке мы опираемся в большей степени на retention.🟡 Второй способ
Одним из способов оценить
lifetime будет определение «точки невозврата», когда неактивные определенное количество дней (7, 14, 30) юзеры, считаются «отвалившимися».🟣 Третий способ
Другой способ - вычисление интеграла от
retention (поскольку lifetime - это площадь под кривой retention) или простое суммирование всех показателей retention. Для такого подсчета нам нужно знать retention за несколько дней, чем больше, тем лучше, так как это будет влиять на точность оценки.Что нам дает lifetime?
Важно иметь в виду, что
lifetime - это средняя цифра, т.е. она необязательно отражает точный день, когда пользователь покинет нас.Вот поэтому он очень полезен - он дает общую картину продукта всего одним числом.
При работе с
lifetime обращайте внимание на сегментацию. Можно делить пользователей по-разному: по стране, полу, устройству, а можно делить по проведенному времени с продуктом. То есть отдельно посмотреть на поведение юзеров с lifetime = неделя, две, месяц - вы сможете увидеть зависимости и, скорее всего, понять причины оттока.Разница между Lifetime и Lifetime Value
Мы не раз видели подобные вопросы от наших студентов. Тут важно понимать, что
LTV больше финансовая метрика (буквально наш доход от юзера за его lifetime). И хотя lifetime, в отличие от LTV, мы измеряем не в рублях, он все равно очень влияет на доход. Чем выше lifetime, тем дольше пользователь будет совершать платежи. Для сервисов с подпиской, это, пожалуй, особенно важные метрики.💥 Более подробно обсуждаем продуктовые метрики: какие бывают, как считать, где применять, как анализировать на нашем Симуляторе «Аналитик данных»!
#analytics #продуктовые_метрики
🔥10👍4❤2
🔥 Возможно, вы не знали этого о циклах for в Python
Недавно поступил вопрос от наших студентов, которые недавно освоили
💡 Загадка
При использовании цикла
🟡 На самом деле, когда мы используем
Но в питоне
✅ При каждой итерации цикла
То есть после выполнения
🖋 А теперь комментарий от наших преподавателей
Если вам действительно необходимо переназначить переменную цикла, используйте
👉 Записывайтесь на наш бесплатный курс по Python, где вы с нуля освоите новый язык программирования!
#python
Недавно поступил вопрос от наших студентов, которые недавно освоили
for-loop в Python и принялись экспериментировать.💡 Загадка
При использовании цикла
for невозможно изменить переменную цикла и повлиять на итерацию:for i in range(5):Как видно, переменная
print(i)
i = 10
#0
#1
#2
#3
…
i не меняется, хотя мы попытались ее переназначить внутри цикла.🟡 На самом деле, когда мы используем
for-loop в Python, никто, как правило, не имеет намерений изменить переменную цикла внутри него. Но можно догадаться, откуда растут ноги. 🙂 Возможно, так могли бы поступить те, кто уже знаком с другими языками программирования, например, С++ или Java.Но в питоне
for-loops не работают таким образом. Изменение переменной цикла не влияет на итерацию.✅ При каждой итерации цикла
for Python извлекает следующий элемент из указанного итерируемого объекта (iterable) - например, range(5). Затем значение этого элемента присваивается переменной цикла - например, i.То есть после выполнения
range(5) или любого другого range(n), объект, созданный range, становится абсолютно независящим от изменений на протяжении итераций. Будто мы написали цикл: for i in [0, 1, 2, 3, 4].🖋 А теперь комментарий от наших преподавателей
Если вам действительно необходимо переназначить переменную цикла, используйте
while, о котором частенько забывают, как только знакомятся с for-loop:i=0Или:
while i < 5:
print(i)
i = 10
#0
i=0Это довольно простая вещь, но о ней стоит помнить при разработке!
while i < 5:
print(i)
i += 2
#0
#2
#4
👉 Записывайтесь на наш бесплатный курс по Python, где вы с нуля освоите новый язык программирования!
#python
👍14🔥9
🔥 Тонкости функции head в Pandas
Сегодня мы поделимся любопытной деталью из мира аналитики данных и нашей практики. Если вы работаете с Pandas, то наверняка знакомы с методом
🟡 Но у
🖋 Такие моменты часто имеют значение, например, при анализе транзакций, чтобы получить список n продуктов с самыми высокими продажами. Или мы, анализируя активность на
🟢 И чтобы избежать этого, мы используем метод
‼️ В нашем бесплатном курсе по Python рассказываем, как работать с модулями и библиотеками Python: как устанавливать, импортировать и какие могут быть подводные камни ☺️
#python #pandas
Сегодня мы поделимся любопытной деталью из мира аналитики данных и нашей практики. Если вы работаете с Pandas, то наверняка знакомы с методом
head(). Он позволяет вывести первые n рядов вашего датафрейма.🟡 Но у
head() есть нюанс. Если данные содержат повторяющиеся значения, head() просто вернет первые строки и не станет учитывать их. Показываем пример:import pandas as pd
df = pd.DataFrame(
[['Игорь', 95],
['Яна', 100],
['Петр', 97],
['Иван', 95]],
columns = ['Имя', 'Оценка'])
df.sort_values('Оценка', ascending=False).head(3)
| | Имя | Оценка |
|---|-------|--------|
| 1 | Яна | 100 |
| 2 | Петр | 97 |
| 0 | Игорь | 95 |
В данном случае мы отсортировали датафрейм по столбцу 'Оценка' и просим вывести три первых позиции. Но если обратить внимание на значения оценок, то заметите, что у двух людей они равны. И если эти данные для вас важны, то использование head() может быть ошибкой.🖋 Такие моменты часто имеют значение, например, при анализе транзакций, чтобы получить список n продуктов с самыми высокими продажами. Или мы, анализируя активность на
itresume.ru при отборе страниц с наибольшим количеством посещений, не можем ограничиться head() - нам важны все значения (даже повторяющиеся).🟢 И чтобы избежать этого, мы используем метод
nlargest() вместо head(). Он позволяет извлекать верхние k строк отсортированного датафрейма, учитывая повторяющиеся значения. Давайте рассмотрим пример:df.nlargest(n=3,
columns='Оценка',
keep='all')
| | Имя | Оценка |
|---|-------|--------|
| 1 | Яна | 100 |
| 2 | Петр | 97 |
| 0 | Игорь | 95 |
| 3 | Иван | 95 |
Здесь мы указываем желаемое поведение для повторяющихся значений, используя параметр keep. В данном случае просим сохранить все строки с равными наивысшими оценками.‼️ В нашем бесплатном курсе по Python рассказываем, как работать с модулями и библиотеками Python: как устанавливать, импортировать и какие могут быть подводные камни ☺️
#python #pandas
🔥22👍13
🔥 CTE-запрос вместо case/when конструкций
В каждом посте мы делимся тем, что знаем и ежедневно используем. Но всего знать невозможно, и мы каждый день учимся и узнаем что-то новое. И рады делиться этим!
📎 Недавно мы наткнулись на очень любопытную конструкцию! Допустим, имеется таблица температур в различных локациях
🟣 Какая самая классическая задача для такой таблицы? Да, распределить значения на: жарко, тепло, холодно. Как чаще всего это реализуется? С помощью нескольких
🟢 Понятная классика! А мы нашли кое-что интереснее:
Не сказать, что эта запись короче, но посмотрите на сам подход!
👨🏻🎓 Те, кто не знаком с типами диапазонов, могут смутиться, увидев конструкцию
Возвращаясь к математике: круглые скобки означают, что граничные значения не входят в диапазон, а квадратные, что входят. Таким образом,
Отсутствующее значение
И последнее: необычный оператор
🤔 Может показаться, что это ненужное усложнение обыденной задачи, но спешим не согласиться! Данная задача - конечно проста, для облегчения понимания, но в условно больших таблицах бывает необходимо категоризировать несколько столбцов. Тогда для каждого из них придется писать
Вдобавок, для изменения или дополнения параметров категоризации, во втором варианте (в отличие от case/when) нам не придется затрагивать основной запрос - просто вносим правки в CTE и готово!
#sql
В каждом посте мы делимся тем, что знаем и ежедневно используем. Но всего знать невозможно, и мы каждый день учимся и узнаем что-то новое. И рады делиться этим!
📎 Недавно мы наткнулись на очень любопытную конструкцию! Допустим, имеется таблица температур в различных локациях
weather_stations:| station | temperature |P.S.: Данные, очевидно, фейковые 🙂
|---------|-------------|
| Moscow | 18.40 |
| Paris | 20.90 |
| London | 14.50 |
| Rome | 23.10 |
🟣 Какая самая классическая задача для такой таблицы? Да, распределить значения на: жарко, тепло, холодно. Как чаще всего это реализуется? С помощью нескольких
case/when конструкций: (карточка 1)🟢 Понятная классика! А мы нашли кое-что интереснее:
CTE-запрос, с использованием numrange (карточка 2)Не сказать, что эта запись короче, но посмотрите на сам подход!
👨🏻🎓 Те, кто не знаком с типами диапазонов, могут смутиться, увидев конструкцию
'( 0,10)' и тип данных numrange. Numrange - один из нескольких диапазонных типов, и он предназначен для диапазона числовых значений (бывают еще tsrange - для timestamp, daterange - для дат и другие).Возвращаясь к математике: круглые скобки означают, что граничные значения не входят в диапазон, а квадратные, что входят. Таким образом,
'(0,10]' означает "от 0, но не включая 0, и до 10 включительно".Отсутствующее значение
'[36,)' означает любое значение после, если это второе значение, или любое значение до, если первое - '(,0]'.И последнее: необычный оператор
<@ означает включен ли некоторый элемент в некоторый диапазон.🤔 Может показаться, что это ненужное усложнение обыденной задачи, но спешим не согласиться! Данная задача - конечно проста, для облегчения понимания, но в условно больших таблицах бывает необходимо категоризировать несколько столбцов. Тогда для каждого из них придется писать
case/when конструкцию. А формирование такого универсального CTE избавит от повторяющихся фрагментов и повысит читабельность.Вдобавок, для изменения или дополнения параметров категоризации, во втором варианте (в отличие от case/when) нам не придется затрагивать основной запрос - просто вносим правки в CTE и готово!
#sql
🔥16👍3🎉1
🔥 Создание поля объектов в Python с помощью setattr()
В работе с Python порой возникают ситуации, когда нужно динамически создавать поля объектов. Например, вы можете столкнуться с задачей занесения данных из словаря в атрибуты класса (мы столкнулись с такой задачей 🙂).
Код, который вы напишете для этой задачи, должен уметь обрабатывать различные словари со своим набором ключей и значениями. Неординарная задача. Но мы знаем, как это сделать!
🟢 Один из способов решения этой задачи - использовать функцию
Например, предположим, что у нас есть словарь my_dict:
📎 Такой подход кажется крайне удобным, потому что мы автоматизируем создание атрибутов и избегаем ручной обработки.
💡 Кроме того, функция
‼️ Чтобы освоить или улучшить свои навыки программирования на Python, присоединяйтесь к нашему бесплатному курсу!
#python
В работе с Python порой возникают ситуации, когда нужно динамически создавать поля объектов. Например, вы можете столкнуться с задачей занесения данных из словаря в атрибуты класса (мы столкнулись с такой задачей 🙂).
Код, который вы напишете для этой задачи, должен уметь обрабатывать различные словари со своим набором ключей и значениями. Неординарная задача. Но мы знаем, как это сделать!
🟢 Один из способов решения этой задачи - использовать функцию
setattr(). Эта функция позволяет динамически назначать поля объекта во время выполнения программы. Она принимает три аргумента: объект, имя атрибута и значение атрибута.Например, предположим, что у нас есть словарь my_dict:
my_dict = {
'name': 'Максим',
'age': 25,
'city': 'Москва'
}
Мы можем создать объект Person и использовать функцию setattr() для присвоения значений атрибутам:class Person:В результате мы получим объект Person с атрибутами name,
pass
p = Person()
for k, v in my_dict.items():
setattr(p, k, v)
age и city.📎 Такой подход кажется крайне удобным, потому что мы автоматизируем создание атрибутов и избегаем ручной обработки.
💡 Кроме того, функция
setattr() может пригодиться в других ситуациях, когда нужно динамически создавать поля объекта. Например, при работе с API или базами данных, когда набор полей может меняться в зависимости от запроса пользователя.‼️ Чтобы освоить или улучшить свои навыки программирования на Python, присоединяйтесь к нашему бесплатному курсу!
#python
🔥12👍7
🔥 Как «распаковать» массив в PostgreSQL?
В прошлых постах мы успели затронуть массивы в SQL и выяснили, что многие не сталкиваются с ним или вообще избегают, так как просто не умеют с ними работать.
На самом же деле все просто. В PostgreSQL есть множество функций, связанных с массивами. Начнем с
🟢 Функция
В более старых версиях PostgreSQL для этого приходилось использовать медленные и сложные методы, но с
Как использовать функцию unnest() в PostgreSQL?
Просто передайте ей массив, и она "распакует" его значения в строки таблицы.
Синтаксис:
А что насчет многомерных массивов?
Мы просто будем использовать синтаксис
🖋 А теперь попробуйте решить такую задачку:
> У вас есть таблица "books", где для каждой книги указаны ее ID и список авторов (хранится как массив). Используя функцию unnest(), найдите все книги, написанные авторами, чьи имена начинаются на букву "A".
Пишите ваши запросы в комментариях!
#sql
В прошлых постах мы успели затронуть массивы в SQL и выяснили, что многие не сталкиваются с ним или вообще избегают, так как просто не умеют с ними работать.
На самом же деле все просто. В PostgreSQL есть множество функций, связанных с массивами. Начнем с
unnest() - самой простой для понимания, на наш взгляд.🟢 Функция
unnest() позволяет "распаковать" массивы в строки. Это очень удобно, если нужно отобразить массивы в виде простой таблицы.В более старых версиях PostgreSQL для этого приходилось использовать медленные и сложные методы, но с
unnest() все стало гораздо проще.Как использовать функцию unnest() в PostgreSQL?
Просто передайте ей массив, и она "распакует" его значения в строки таблицы.
Синтаксис:
unnest(array)
🟡 Например, если есть массив с числами от 1 до 5, то можно применить функцию unnest() и получить каждое число в отдельной строке таблицы.SELECT unnest (ARRAY[1,2,3,4,5]);
| | unnest |Теперь давайте посмотрим, как сработает функция, если передать ей текст, а не цифры.
|---|--------|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
SELECT unnest (ARRAY['яблоко', 'лимон', 'банан']);
| | unnest |Видим, что она работает одинаково как для строковых значений, так и для чисел.
|---|---------|
| 1 | яблоко |
| 2 | лимон |
| 3 | банан |
А что насчет многомерных массивов?
SELECT unnest (array[array[1, 2], array[2, 3], array[4,5]]);
| | unnest |А если с несколькими массивами разных типов данных? Запросто.
|---|--------|
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 3 |
| 5 | 4 |
| 6 | 5 |
Мы просто будем использовать синтаксис
unnest (array1, array2, array3…):SELECT * FROMА если они разных размеров?
unnest
(
array [1, 2, 3],
array ['HP', 'AMD', 'APPLE']
)
AS data(ID, Company);
| | id | company |
|---|----|---------|
| 1 | 1 | HP |
| 2 | 2 | AMD |
| 3 | 3 | APPLE |
SELECT * FROMЕсли массивы имеют разное число элементов, то функция автоматически дополнит их
unnest
(
array [1, 2, 3],
array ['HP', 'AMD', 'APPLE', 'DELL']
)
AS data(ID, Company);
| | id | company |
|---|--------|---------|
| 1 | 1 | HP |
| 2 | 2 | AMD |
| 3 | 3 | APPLE |
| 4 | [NULL] | DELL |
NULL - значениями до нужного размера.🖋 А теперь попробуйте решить такую задачку:
> У вас есть таблица "books", где для каждой книги указаны ее ID и список авторов (хранится как массив). Используя функцию unnest(), найдите все книги, написанные авторами, чьи имена начинаются на букву "A".
Пишите ваши запросы в комментариях!
#sql
👍12🔥8