7.34K subscribers
1.74K photos
75 videos
1 file
1.32K links
Привет! Мы — образовательная платформа в сфере аналитики Simulative: simulative.ru

Создаём курсы-симуляторы, где обучаем не на «апельсинках», а на кейсах из реального бизнеса.

Наш уютный чат: @itresume_chat
Поддержка: @simulative_support
Download Telegram
🔥 Давайте проведем live coding?

Ребят, у нас возникла идея - а давайте покодим в прямом эфире? Например, решим какое-нибудь тестовое задание по SQL или Python на позицию Аналитика Данных 🙃

🟢 Если вам нравится эта мысль - поставьте, пожалуйста, реакцию на это сообщение. Так мы поймем, что интерес есть и в ближайшее время вернемся с приглашением 🤟🏻

P.S. Если вы хотите другую тему для лайвкодинга - напишите об этом в комментариях. Мы с удовольствием возьмем ее в работу.

P.P.S. Если у вас есть классное тестовое задание, которые было бы круто порешать в прямом эфире - напишите в личку
@andron233
🔥108👍33
🔥 Лайвкодинг: «Ща порешаем» в новом Симуляторе «Аналитик данных» с Глебом Михайловым

Недавно мы предложили провести лайвкодинг и вы с энтузиазмом восприняли эту идею.

Поэтому мы решили сделать даже круче: мы дали Глебу Михайлову (кто ж не знает Глеба) доступ к одной главе нашего нового Симулятора «Аналитик данных».

📌 В воскресенье в 19:00 МСК приходите на стрим - Глеб будет делать распаковку симулятора и решать топовые бизнесовые задачи на SQL.

Кстати, крутой подгон - мы также дадим каждому участнику доступ к главе и к задачам: сможете кодить вместе с Глебом 🤟🏻

Короче, ждем всех в воскресенье в 19:00 - будет классно. Посмотрим, сможет ли Глеб симулировать аналитика данных 😈😂
👍18🔥8🎉3
🔥 Начинаем лайвкодить SQL через 5 минут

Это напоминалка о том, что через 5 минут мы начинаем стрим с Глебом. Будем решать крутые задачки по SQL в рамках нашего нового Симулятора «Аналитик данных».

🔗 Ссылка на стрим: https://youtu.be/2jDFud5hRHM. Подключайтесь, будет круто!

Хотите решать вместе с нами? Вот вам ссылочка на Главу 6 «Группировки и агрегации», которую и будет проходить Глеб 👉🏻 https://lms.simulative.ru/gleb/6/1/leopard

А если хотите залететь в Симулятор по выгодной цене - то просто введите промокод dataleopard15 на сайте, он даст вам 15% скидки 😏
👍53
🔥 Долой длинные строки в Python

Во время код-ревью мы часто сталкиваемся с длинными строками кода, которые даже не влезают в экран. И казалось бы - они содержат настолько «стройную» информацию, что даже не знаешь, где (и зачем) поставить перенос на следующую строку.

Вот несколько случаев, где это встречается особенно часто:

* Длинные строки
* Большое количество аргументов в функции
* `method chaining` в Pandas

Рассмотрим такой «длинный» код на примере Pandas. Согласитесь, выглядит жутко:

df = coderun[coderun["cohort"] >= "2022-01"].groupby(["cohort", "language", "user_id"])["problem_id"].agg("nunique").groupby(["cohort", "language"]).agg(np.mean).reset_index().pivot_table(values="problem_id", columns=["language"], index=["cohort"])

А теперь давайте приведем код в порядок. Есть, как минимум, два метода борьбы с такими ситуациями.

🔵 Перенос строки с помощью обратного слеша

Достаточно поставить в конце строки обратный слеш и Python будет воспринимать весь написанный код как единую строку.


df = coderun[coderun["cohort"] >= "2022-01"] \
.groupby(["cohort", "language", "user_id"])["problem_id"] \
.agg("nunique") \
.groupby(["cohort", "language"]) \
.agg(np.mean) \
.reset_index() \
.pivot_table(values="problem_id", columns=["language"], index=["cohort"]


Сами видите - код стал в разы более читаемым и даже компактным.

🔵 Оборачивание круглыми скобками

Прием заключается в том, что мы просто оборачиваем все выражение в круглые скобки и это тоже рассматривается Python как одна строка кода.


df = (
coderun[coderun['cohort'] >= '2022-01']
.groupby(['cohort', 'language', 'user_id'])['problem_id']
.agg('nunique')
.groupby(['cohort', 'language'])
.agg(np.mean)
.reset_index()
.pivot_table(values='problem_id', columns=['language'], index=['cohort'])
)


На наш взгляд, этот вариант даже лучше - нет лишних символов и код выглядит еще более аккуратным.

- - - - -

Кстати, а вы знали про method chaining в Pandas и про способы переноса строк?
🔥24👍3
🔥 Ищем технического редактора (автора контента) к себе в команду

Друзья, мы расширяем команду и ищем человека, который будет помогать нам с контентом во всем его многообразии. Естественно, все на 100% связано с программированием и аналитикой. Вот примеры задач:

* создавать задачи и тесты для нас и наших корпоративных клиентов
* создавать посты в соцсети
* создавать обучающие материалы, пособия, шпаргалки и т.д.

Если вам это интересно - почитать про вакансию можно по ссылке (там же небольшое тестовое):

🔗 ссылка на вакансию

Работа очень интересная и масштабная - каждую единицу созданного вами контента будут видеть и использовать тысячи людей 🔥 Будем ждать вас в нашу команду 🙂

P.S. Идеального знания языков программирования не требуется.

- - - - -

А если эта вакансия может быть интересна вашим друзьям/родственникам/коллегам - обязательно перешлите им, пожалуйста.
👍51
🔥 Агрегирование в Pandas, которым вы не пользовались раньше (наверняка)

Работая с библиотекой Pandas, нередко приходится применять функции группировки и агрегирования. Все мы привыкли к sum, count и прочим распространенным функциям.

Но сегодня нам хотелось бы рассказать об одной интересной функции, которую можно использовать в агрегации. Речь пойдёт о функции set. Она позволит вывести уникальное множество значений для каждой группы.

Более наглядно рассмотрим работу функции на небольшом примере. Представим, что у вас есть датафрейм с id клиента и с наименованием его покупки:

| id | product |
|----|---------|
| 1 | p1 |
| 2 | p2 |
| 1 | p3 |

Для отображения уникальных покупок каждого клиента воспользуемся такой конструкцией:

df.groupby('id').agg({'product': set})

В результате мы получим таблицу:

| id | product  |
|----|----------|
| 1 | {p1, p3} |
| 2 | {p2} |

А какими способами вы бы решили данную задачу? 😏

- - - - - - - - - -

🔗 Хотите прокачаться в аналитике? Ждем вас в Симуляторе «Аналитик данных» →
🔥26
🔥 Можно ли обойтись без OFFSET в SQL?

Команда LIMIT позволяет вывести ограниченное количество записей из таблицы. Например:

SELECT * FROM table
LIMIT 10

Данный запрос выведет первые 10 строк из таблицы.

Но что делать, если необходимо вывести строки, начиная со второй? Скорее всего, вы воспользуетесь командой OFFSET, и это будет верным решением.

Однако, так же можно решить эту задачу следующей конструкцией:

SELECT * FROM table
LIMIT 1, 10

Команда LIMIT отсекает 1 строку и берет следующие 10, которые идут после неё.

⛔️ Обратите внимание, что такой способ работает не во всех СУБД!

Если в MySQL можно написать такой запрос, то в PostgreSQL он выдаст ошибку и придётся воспользоваться командой OFFSET. А в MSSQL так и вовсе нет оператора LIMIT, в этой СУБД используют команду TOP.

- - - - - - - - - -

🔗 Хотите прокачать свой SQL? Заходите решать задачки на платформу IT Resume →
🔥16👍2
🔥 Метрика N-day Retention - важнейшая метрика продукта

Если вы работали с продуктовой аналитикой, вы наверняка слышали о метрике Retention. Но знаете ли вы, что есть несколько видов данной метрики?

Мы решили подготовить для вас небольшие шпаргалки по каждому виду Retention. Начнём, пожалуй, с классической метрики.

N-day Retention - метрика, которая показывает, какой процент клиентов продолжает пользоваться продуктом в конкретный день после знакомства.

Данная метрика является одной из основных. Мало привлечь внимание клиентов к своему продукту, важно ещё и удержать как можно большее количество пользователей.

Рассмотрим как рассчитать n-day Retention на примере.

1 сентября 100 человек познакомились с нашим продуктом (например, установили приложение). Мы решили посчитать n-day Retention седьмого дня. Считаем количество пользователей, которые воспользовались приложением 8 сентября, т.е. спустя 7 дней со дня установки. Таких клиентов оказалось 37. Находим долю этих клиентов:

(37 / 100) * 100% = 37%

То есть мы удержали 37% новых пользователей. Это и есть n-day Retention на седьмой день.

В итоге, чем выше значение n-day Retention, тем меньше отток клиентов.

P.S. стоит так же обратить внимание на специфику продукта. К примеру приложение по поиску авиабилетов будет иметь значение данной метрики ниже, чем соцсеть.

- - - - - - - - - -

🔗 Хотите научиться считать не только n-day, но и другие виды retention в SQL, Excel и не только? Приходите в симулятор “Аналитик данных”!
🔥9👍1
🔥 Лайфхак: работа с датами в связке Excel - Python

Нередко возникают моменты, когда при создании датафрейма на основе Excel файла, даты записываются в различных форматах. Сегодня нам бы хотелось рассмотреть случай, когда дата имеет числовой формат.

Рассмотрим, например, дату 10.01.2022. Если преобразовать её в число в Excel, мы получим 44571, а в Python - 738165.

Для получения даты в числовом виде в Python мы использовали такую конструкцию:

import datetime
datetime.date(2022, 1, 10).toordinal()
# 738165

Почему так происходит? Дело в том, что Excel начинает отсчёт с 1900 года, а Python с 1 года.

И как же быть в таких ситуациях? На помощь приходит библиотека xlrd.

Переведём число 44571 в дату используя конструкцию ниже:

from xlrd.xldate import xldate_as_datetime
print(xldate_as_datetime(44571, 0))
# 2022 - 01 - 10 00:00:00

Браво! Вы великолепны! Вот так с помощью двух строчек можно преобразовать даты к одному формату!

- - - - - - - - - -

🔗 Приходите к нам на платформу, у нас есть интересные задачи на Python и не только: IT Resume
👍10🔥4🎉1
🔥 Ищем технического редактора (автора контента) к себе в команду

Друзья, мы расширяем команду и ищем человека, который будет помогать нам с контентом во всем его многообразии. Естественно, все на 100% связано с программированием и аналитикой. Вот примеры задач:

* создавать задачи и тесты для нас и наших корпоративных клиентов
* создавать посты в соцсети
* создавать обучающие материалы, пособия, шпаргалки и т.д.

Если вам это интересно - почитать про вакансию можно по ссылке (там же небольшое тестовое):

🔗 ссылка на вакансию

Работа очень интересная и масштабная - каждую единицу созданного вами контента будут видеть и использовать тысячи людей 🔥 Будем ждать вас в нашу команду 🙂

P.S. Идеального знания языков программирования не требуется.

- - - - -

А если эта вакансия может быть интересна вашим друзьям/родственникам/коллегам - обязательно перешлите им, пожалуйста.
🔥61👍1
🔥 Извлекаем абсолютно любые числа из строки с помощью регулярного выражения

Представьте, что вам дана строка, содержащая:

✓целые/дробные положительные/отрицательные числа
✓числа в стандартной записи и в научной записи (2e-10)
✓абсолютно что угодно еще

🧠 А теперь решите задачу:

Нужно извлечь из этой строки только числа, притом во всех форматах.

Как это сделать? А давайте воспользуемся регулярными выражениями! Для примера возьмем строку:

s = '(3.22128 какой-то текст 0.353403 -0.0194664 еще какой-то текст 2e-15 some more text 15. 5 50e -100 )'

А теперь напишем такой код:

import re

[eval(el[0]) for el in re.findall('(-?\d+(e-\d+|.\d+)*)', s)]

🧐 На выходе мы получим список из чисел и ничего лишнего. Но как это получилось?!

💡А очень просто: здесь с помощью регулярного выражения мы находим «кусочки», которые удовлетворяют шаблону. Давайте дадим небольшой комментарий:

-?

Перед числом может стоять знак «минус», а может и не стоять.

\d+

Затем идет некая последовательность цифр (либо целая часть числа, либо основание в научной записи)

(...|...)*

Затем может идти один из вариантов, разделенных |

e-\d+

Научная запись: символ e, после которого идет - и какая-то последовательность цифр

.\d+

Дробная часть: точка, а после нее цифры

(...)

Финально оборачиваем все в скобки, чтобы извлечь полное число, а не его дробную/целую часть

С помощью сервиса regex101 вы можете удобно протестировать все возможные вариации строк с этой регуляркой. Работает железно и достойно ваших сохраненок 😁

- - - - -

🔗 Хотите научиться также просто решать боевые задачи? Приходите в симулятор «Аналитик данных»!
🔥24👍2
🔥 Приходите к нам на онлайн мастер-класс по SQL

Завтра проводим бесплатный онлайн мастер-класс по SQL. Будем вас ждать! 😍

Ваш первый кейс в аналитике данных: исследуем продажи аптек

🎄 Дата: 21 декабря, среда
🎄 Время: 20:10 по Мск
🎄 Площадка: Youtube
🎄Бесплатно

Будем разбираться в SQL, обсуждать разные фишечки, писать ad-hoc запросы и анализировать деятельность реального бизнеса. Короче, будет интересно!

Ссылка на подключение и раздаточный материал придет сюда → ссылка, подписывайтесь 🙂
🔥12👍3
🔥 Уже скоро начнется наш онлайн мастер-класс по SQL

Напоминаем, что сегодня в 20:10 по Мск мы проводим мастер-класс по SQL. Что будем делать:

* Анализировать программу лояльности в аптечной сети
* Считать продуктовые метрики: LTV, ARPPU и другие
* Обсуждать интересные функции и приемы (unpivot, age и многое другое)

🔗 Ссылочка на вебинар, доступ к реальному кластеру и конспект-методичка доступны здесь 👉🏻 ссылка

Приходите, будет интересно! 🙂
👍4🔥21🤩1
Друзья, мы начинаем! 🔥

Ссылка на мастер-класс 👉🏻 https://www.youtube.com/watch?v=VhlgGlNn8B8
👍3🔥21
«Пишем цикл в одну строку» или list comprehension

При проверке домашних работ наших студентов мы часто натыкаемся на конструкцию такого вида:

lst = [1, 2, 3]

result = []
for el in lst:
if el % 2 == 0:
result.append(el)

Однако, Python замечателен тем, что позволяет писать элегантный, и почти такой же простой для чтения код, как обычный английский. Поэтому, можете даже не сомневаться, почти всегда есть возможность, сделать Ваш код короче. В нашем примере можно использовать list comprehesion.

result = [i for i in lst if i % 2 == 0]
>> [2]

🧠 Давайте разберемся как это работает.

Новый список = [выражение for элемент in iterable (if условие)]

✓ В выражении мы можем задать только элемент, вызвать какой-либо метод или обозначить выражение, возвращающее значение.

For элемент in iterable - это та же конструкция, которую мы используем в циклах for.

✓ А условие позволяет нам, одновременно с генерацией списка, добавлять фильтрацию.

Если Вы думаете, что это и так уже достаточное упрощение, Python снова позволяет нам сделать еще больше, и все в одну строку!

Что если нам нужны три условия?

result = [i for i in lst if i % 2 == 0 and i > 1 or i == 3]
>> [2, 3]

Или такая конструкция:

result = [i**2 for i in lst if i % 2 == 0 or i in [5, 9, 4, 7]]
>> [1, 4]

Тут уже непонятно кто кого проверяет на прочность. То ли мы Python, то ли Python нас…

Но давайте попробуем прочесть: для каждого i в lst, возвести i в квадрат и если i**2 четное или есть в переданном в условие списке - добавить в result. Уже стало понятнее!

💡 Прекрасно, скажете Вы, мы можем написать 4 строки кода в одной, а есть ли в этом практический смысл?

Допустим, у нас есть список из 10000 элементов, нам нужно его отфильтровать и сформировать новый. Цикл for отработает за 417 µs, а list comprehension - за 289 µs. Почти в два раза быстрее.

Теперь у вас есть не только эстетическая мотивация разобраться, но и практическая. А когда станет совсем легко, приглашаем ознакомиться с двойным list comprehension, мы рассказывали про него здесь!
🔥12👍81
🔥 «Большой О» уже стал вашим другом?

Обращали ли Вы когда-нибудь внимание на то, за сколько времени отрабатывает Ваш код?

Когда мы учимся, мы думаем «хорошо, что вообще отработал». Однако, в дальнейшем, это может сыграть злую шутку. Когда Вы приступите к большим проектам (а мы в этом не сомневаемся), придется чаще думать над ускорением работы, уменьшением объема памяти и многих других вещах. А BIG O или О-нотация станет Вашим большим помощником.

Вы, наверняка, уже возмутились, ведь время выполнения алгоритма зависит от устройства, на котором он запускается. Вы правы, но также и от количества входных данных.

Как же тогда это оценивать?

Ответ: BIG O или О-нотация - Ваш неизменный помощник в вопросе сложности алгоритма.

Главное! BIG O показывает то, насколько сильно увеличивается время работы при увеличении входных данных. Это гораздо лучшая метрика для оценки, чем конкретное время работы!

Давайте сразу к примерам:

O(n): при n=1 делается 1 шаг. При n=10 делается 10 шагов.
O(n²): при n=1 делается 1 шаг. При n=10 делается 100 шагов.

Заметьте, при n=1 эти двое будут работать одинаково!

Еще один замечательный пример: линейный и бинарный поиск.

Не вдаваясь в подробности, сложность линейного поиска - O(N), выглядит неплохо. Это, по сути, означает, что при увеличении входных данных в 2 раза, понадобится в 2 раза больше времени. Если данных будет в 100 раз больше, то и времени нам потребуется x100.

Сложность бинарного поиска - O(log N). Немного посчитав, обнаружим, что при увеличении входных данных, например, в 100 раз, затраченное время увеличится не в 100 раз (как в примере выше), а всего в 2,5 раза.

Существенная экономия, и это при условии, что BIG O оценивает худший вариант - то есть искомый элемент будет самым последним.

Решить одну и ту же проблему зачастую можно многими способами. Задача умелого программиста — выбрать самый подходящий. Знание таинственной O-нотации поможет заранее понимать как алгоритм будет проявлять себя в работе. Звучит как конкурентное преимущество, неправда ли?

Мы ближе познакомимся с BIG O в следующих постах, следите за обновлениями!

🏋️‍♀️ А пока разминка 👉 вы сможете написать алгоритм для чисел Фибоначчи за О(1)?
🔥7👍51🤩1
🔥 Ключевая метрика нашего бизнеса - rolling retention. Шпаргалка.

Встречайте rolling retention. Продолжаем нашу серию шпаргалок. Мы уже рассказывали вам про n-day retention вот 👉🏻 тут.

Давайте освежим ваши знания. Допустим, у нас 2 пользователя, один пользователь вернулся на 14-й день и на 45-й день, а второй пользователь - только на 44-й день. Каким будет n-day retention 14 дня? Верно, 50%. А rolling retention будет 100%. Как? А вот как!

❗️Rolling retention - это процент пользователей, которые вернулись к продукту в день N с момента знакомства или в любой из последующих дней.

🟢 Давайте сразу посмотрим пример.

У нас есть данные по 4 пользователям за 6 дней. Дни, когда пользователи взаимодействовали с продуктом - выделены галочкой, если поле пустое - пользователь был неактивен.

Посчитаем для них «классический» retention и rolling.

           | **День 1** | **День 2** | **День 3** | **День 4** | **День 5** | **День 6** 
-----------|------------|------------|------------|------------|------------|------------
User 1 | ✓ | ✓ | ✓ | | ✓ | ✓
User 2 | ✓ | ✓ | | ✓ | |
User 3 | | | | | |
User 4 | | ✓ | | | | ✓
Retention | 2/4 50% | 3/4 75% | 1/4 25% | 1/4 25% | 1/4 25% | 2/4 50%
Rolling | 3/4 75% | 3/4 75% | 3/4 75% | 3/4 75% | 2/4 50% | 2/4 50%

Заметно, что rolling retention выше, чем “классический”, потому что он учитывает не только пользователей, которые были активны в один конкретный день, но и всех тех пользователей, которые вернулись позже.

Однако, на практике, с rolling retention бывают сложности. Например, у нас были пользователи, которых мы посчитали «отвалившимися», и при расчете rolling retention мы перестали их учитывать, а они вдруг взяли и вернулись! Теперь нам придется пересчитать rolling retention за все предыдущие дни. Но не пугайтесь сразу, обычно эта метрика считается динамически на дашбордах и т. п., так что эту работу за Вас сделает сама BI-система или интерактивный отчет 😊

Например, в последний раз пользователь был активен в 10-й день после первого контакта с продуктом. Затем мы рассчитали rolling retention на 25-й день, уже более не рассматривая этого пользователя. Однако он проявил активность на 30-й день. И чтобы учесть это - потребуется обновить rolling retention за все дни с 11-го по 30-е.

💡Где же это может быть удобно?

В то время как «классический» retention удобен для продуктов, которые используются ежедневно: соцсети, почта, игры. Rolling retention будет идеален для продуктов нерегулярного пользования, например, сайтов продажи авиабилетов. Он явно покажет, что пользователь может не быть активным каждый день, но все еще оставаться с нами. А еще мы в IT Resume активно используем эту метрику 😀

🎁 Хотите освоить аналитику данных с нуля на кейсах из реальной бизнес-практики? Присоединяйтесь к симулятору «Аналитик данных» со скидкой 50% до 31 декабря → ссылка на Симулятор

#продуктовые_метрики
🔥7👍3🤩1
Кто сидит с телефона - прикладываем табличку в виде картинки, чтобы было лучше видно 🙂
🔥92
🔥 3 строки, которые написал бы middle в Pandas

1️⃣

Используете ли вы .query? Зачастую, когда необходимо отфильтровать датафрейм мы видим следующую конструкцию:

df.loc[(df['Adults'] < 3) & (df['Children'] > 1)]

В выбранном здесь синтаксисе нет ничего плохого. Однако многие новые пользователи забывают, что в Pandas можно писать большие запросы, используя .query:

df.query('Adults < 3 and Children > 1')

И чем сложнее будут становится ваши запросы, тем сильнее вы прочувствуете полезность .query.


2️⃣

Часто бывает так, что у нас есть переменная, к которой мы хотим обратиться в запросе. Как бы Вы это сделали? Наш топ встречаемого кода:

- Конкатенация

df.query('Adults < ' + str(min_adults) + 'and Children > ' + str(min_children))

- f-строки

df.query(f'Adults < {min_adults} and Children > {min_children}')

А знали ли вы, что ко внешним переменным можно просто обратиться через @?

df.query('Adults < @min_adults and Children > @min_children')


3️⃣

И напоследок, используя .query нам бывает необходимо сформировать из результирующего датафрейма - новый.

df_families = df.query('Adults < 3 and Children > 1')

Однако, когда мы решим изменить новый датафрейм, мы получим предупреждение SettingWithCopyWarning.

df_families['First_name'] = df_families['Name'].str[-5:]

Дело в том, что Pandas позволяет нам выполнять, так называемую, цепную индексацию. Это повторный выбор строк/столбцов из результата предыдущего выбора строк/столбцов. Однако же, при подобных манипуляциях, предсказать что вернет нам Pandas - копию или представление - практически невозможно. Поэтому, чтобы обезопасить себя и быть уверенным в том, что модификации не появятся там, где их не ждали, лучше воспользоваться методом copy().

df_families = df.query('Adults < 3 and Children > 1').copy()

df_families['First_name'] = df_families['Name'].str[-5:]

Он, по умолчанию, создаст глубокую копию и любые изменения в нашем новом датафрейме не отразятся в оригинальном.

- - - - -

🎁 Присоединяйтесь к симулятору «Аналитик данных» со скидкой 50% до 31 декабря → ссылка на Симулятор

#python #pandas
👍19🔥7🤩1
🔥 Типичная ошибка в SQL: приоритет операторов

Часто в обучении встречаются задачи, где в WHERE нужно передать несколько условий, и, порой, остальной запрос может быть верным, но будет возвращать некорректный результат из-за приоритета операторов.

Живой пример: у нас есть таблица с информацией о разработчиках, которая содержит ФИО, язык разработки и уровень (junior/middle/senior).

Если нам нужно будет выбрать только middle и senior, мы запросто используем запрос:

SELECT ...
WHERE level = 'middle' OR level = 'senior'

(Надеемся вы знаете, что если вместо OR поставить AND- получим совсем не то, что нужно)

Усложняемся: найдем всех middle и senior, пишущих на Python:

SELECT ...
WHERE level = 'middle' OR level = 'senior' AND language = 'python'

Все верно? Вот что мы получим:

| name    | language | level  |
|---------|----------|--------|
| Дмитрий | python | senior |
| Валерий | php | middle |
| Наталья | python | middle |
| Валерия | python | middle |

В результирующей таблице появился php-разработчик, а мы его, как будто, и не просили.

Дело в том, что операторы OR и AND имеют разный приоритет, и у AND он - выше. Запрос сначала выбирает senior, использующих python, а далее срабатывает OR, который добавляет всех middle.

Чтобы получить верный результат можно написать:

SELECT ...
WHERE level = 'middle' AND language = 'python' OR level = 'senior' AND language = 'python'

А лучше еще проще:

SELECT ...
WHERE (level = 'middle' OR level = 'senior') AND language = 'python'

Когда в одном запросе Вам приходится использовать и OR, и AND - обращайте внимание на порядок выполнения, иначе можно запросто получить неверные данные. Особенно, если не знать, как выглядит исходная таблица и необходимый результат. А чтобы полностью обезопасить себя от ошибок с OR и AND - используйте скобки.

Легко заметить ошибку, когда мы явно видим, что не все строки удовлетворяют нашему условию, но когда строк миллион - найти такую ошибку будет уже невозможно.

Чувствуете уверенность в этой теме? Попробуйте решить задачу!

#sql
🔥20👍82
🔥 А вы знаете разницу между range between и rows between?

Давайте проведем с вами небольшой код ревью! Рассмотрим два небольших запроса и сравним их результаты.

1️⃣ Запрос первый:

SELECT SUM(revenue) OVER(
PARTITION BY shop
ORDER BY period ASC
ROWS UNBOUNDED PRECEDING
) AS cumulative_revenue
FROM revenue

2️⃣ Запрос второй:

SELECT SUM(revenue) OVER(
PARTITION BY shop
ORDER BY period ASC
RANGE UNBOUNDED PRECEDING
) AS cumulative_revenue
FROM revenue

Что скажете? Одинаково ли они отработают?

Затрудняетесь с ответом? 🤔 Мы сейчас все расскажем!

Несомненно, вы знаете, что как ROWS, так и RANGE в SQL ограничивают строки внутри партиции оконных функций.

Однако, ROWS делает это «в лоб». Он просто определяет фиксированное количество строк, которые предшествуют или следуют за текущей строкой, не принимая во внимание их значения.

В то время как RANGE ограничивает строки «логически». Это означает, что он учитывает не только количество предыдущих/следующих строк, но также берет во внимание значения в других строках по сравнению с текущей строкой.

Показываем!

Пройдемся построчно по первому коду, использующему ROWS.

🟢 Берём доход (для текущей строки) + cumulative_revenue (из предыдущей строки) = cumulative_revenue (для текущей строки). И так для каждого shop в таблице revenue.

В случае, если у нас появятся «дубликаты» (shop и period будут иметь одинаковые значения, а revenue будет отличаться) ROWS просто не обратит на это внимания, он продолжит брать доход текущей строки, прибавит cumulative_revenue предыдущей и выдаст новую cumulative_revenue.

🔵 Вы наверное уже догадались в чем подвох RANGE? Он, в свою очередь, будет использовать все предыдущие строки, текущую строку, а еще учтет строки содержащие одинаковые shop и period.

И как же он с ними будет работать? Он обработает их вместе, сложив их revenue. То есть, доход (для текущей строки) + доход (для всех остальных строк с таким же shop и period) + cumulative_revenue (для предыдущей строки) = новый cumulative_revenue. Таким образом, мы получим единое значение совокупного дохода за период.

Это может показаться вам несущественной разницей, однако в реальном мире к концу периода не может быть двух разных значений совокупного дохода. А знание отличий RANGE и ROWS и их уместное использование существенно повысит ваш профессиональный уровень!

- - - - -

🎁 Присоединяйтесь к симулятору «Аналитик данных» со скидкой 50%, там мы подробно разбираем бизнес-кейсы с использованием SQL и Python → ссылка на Симулятор

#sql
🔥11👍4😱1