Про SQL Wildcards
Я решила поэкспериментировать с форматом и посмотреть, что из этого выйдет)
⭐ Все знают про %, но про остальные я думала, что они существуют в регулярках в программировании, но никак не в эскуэль.
Пока не увидела в коде запросов, например:
Для любителей почитать вот ссылки на оф. доки:
Postgres
MS SQL Server
MySQL
#sql_tips
Я решила поэкспериментировать с форматом и посмотреть, что из этого выйдет)
Пока не увидела в коде запросов, например:
--эквивалентны
and Action_Code like 'K[HS]'
and Action_Code = 'KH' or Action_Code = 'KS'
--тоже эквивалентны
and Assignment_Value like '%CRE[12]%'
and Assignment_Value like '%CRE1%' or Assignment_Value like '%CRE2%'
Для любителей почитать вот ссылки на оф. доки:
Postgres
MS SQL Server
MySQL
#sql_tips
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥30⚡2👨💻2💯1
count(), F.count(), F.countDistinct(), distinct()
В спарке есть несколько функций count, которые меня вначале путали, и тут я хочу расставить все точки над i.
1️⃣ count() - это действие
Оно запустит весь пайплайн расчетов и выведет на экран одно число - количество строк в датафрейме:
Также можно использовать в агрегации, но нельзя поменять название столбца (будет count):
2️⃣ F.count() - это трансформация, агрегирующая функция
В отличие от первого способа в агрегации можно поменять название столбца:
Отличия count() и F.count():
3️⃣ F.countDistinct() - тоже агрегирующая функция
Тут вариант агрегации только один, потому что df.countDistinct() не существует:
При этом в спарке есть еще функция distinct(), которая тоже вносит некую путаницу.
Отличия distinct().count() и F.countDistinct():
#spark
В спарке есть несколько функций count, которые меня вначале путали, и тут я хочу расставить все точки над i.
Оно запустит весь пайплайн расчетов и выведет на экран одно число - количество строк в датафрейме:
df.count()
Также можно использовать в агрегации, но нельзя поменять название столбца (будет count):
df.groupBy('category')
.count()
.orderBy('count')
.show()df.select(F.count('id')).show()В отличие от первого способа в агрегации можно поменять название столбца:
df.groupBy('category')
.agg(F.count('id').alias('cnt'))
.orderBy('cnt')
.show()Отличия count() и F.count():
# результат - датафрейм с одной ячейкой
df1.select(F.count('id')).show()
# +---------+
# |count(id)|
# +---------+
# | 3|
# +---------+
# результат - число
df1.select('id').count()
# 3
df.select(F.countDistinct('id')).show()Тут вариант агрегации только один, потому что df.countDistinct() не существует:
df.groupBy('category')
.agg(F.countDistinct('id'))
.show()При этом в спарке есть еще функция distinct(), которая тоже вносит некую путаницу.
Отличия distinct().count() и F.countDistinct():
# результат - датафрейм с одной ячейкой
df1.select(F.countDistinct('id')).show()
# +------------------+
# |count(DISTINCT id)|
# +------------------+
# | 2|
# +------------------+
# результат - число
df1.select('id').distinct().count()
# 2
#spark
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7🔥5🌚1
Как из деления int/int получить double?
🤓 Вам нужно что-то посчитать: поделить одно количество на другое и округлить результат до 2х знаков после запятой.
Так как количество - это целое число, если написать просто count1/count2, то в результате мы получим тоже целое число: 15/26 = 0. А мы хотим 0.57692307692307692308 - вот оно самое.
✨ Поэтому умножаем на 1.0, и вуаля✨
#sql_tips
Так как количество - это целое число, если написать просто count1/count2, то в результате мы получим тоже целое число: 15/26 = 0. А мы хотим 0.57692307692307692308 - вот оно самое.
SELECT round(count1 * 1.0 / count2, 2)
FROM test
#sql_tips
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤3🌚2
Сегодня у нас прошло очередное демо трайба!
Команда
В кластере несколько команд, а в трайбе несколько кластеров (всего где-то 15 команд +-).
Что было?
Ну, и вкусный фуршетик
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤3😁2🆒1
В продолжение поста про вредные советы есть еще несколько лайфхаков (уже нормальных!):
SELECT
e.emp_no
, e.first_name
--, e.last_name
, s.salary
FROM employees e
JOIN salaries s
ON e.emp_no = s.emp_no
final_df = (
employees.alias('e')
.join(salaries.alias('s'), F.col('e.emp_no') == F.col('s.emp_no'), 'inner')
.select(
'e.emp_no',
'e.first_name',
's.salary'
)
)
1=1, чтобы тоже быстро закомментить и прогнать:SELECT *
FROM employees
WHERE 1=1
--AND date_joined <= '2024-01-01'
AND is_deleted = 0
AND username != 'system'
Если бы
WHERE date_joined <= '2024-01-01' шло на первом месте, то пришлось бы убирать AND перед вторым условием, удалять лишние пробелы - в общем, неудобно, если часто так делать.#sql_tips #spark
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👏4💯2
Задачка
Есть 3 таблички:
1️⃣ Cities (id, city, region)
2️⃣ Couriers (id, fio)
3️⃣ Orders (id, datetime, cost, city_id, courier_id)
Найти топ 10 курьеров для каждого города, которые доставили больше всего заказов за март.
Есть 3 таблички:
Найти топ 10 курьеров для каждого города, которые доставили больше всего заказов за март.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4🔥2
Домашку проверила) В целом, у всех плюс-минус похожие варианты
Отметила несколько моментов:
--тут не войдет 31 число
WHERE datetime >= '2024-03-01' AND datetime < '2024-03-31'
--тут за 31.03 войдет только 00:00:00
WHERE datetime between '2024-03-01' AND '2024-03-31'
--поэтому так правильнее
WHERE datetime > '2024-03-01' AND datetime < '2024-04-01'
Ну, и всякие extract/date_part тоже подойдут.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👌1
Помогите закрыть таску!😘
💻 Исходные данные
У нас есть три вьюшки с id и json-полем. Вьюшки собираются по разным фильтрам.
📌 Цель: собрать массив степов, при этом дополнить предыдущие недостающие степы значением default_json.
🎥 Пример:
для id = 1: [json]
для id = 2: [default_json, json]
для id = 3: [default_json, default_json, json]
и т.д.
При этом в default_json прокидывается текущий степ, поэтому нам нужно не потерять это название.
🚀 Пока идея такая:
- делаем full join
- делаем unpivot
- добавляем флаг is_missed на основе null
- итерируемся с конца в рамках id и удаляем все is_missed = 1, пока не найдём is_missed = 0
Лично мне это кажется слишком громоздкий и малочитаемым, поэтому хочется двинуться в сторону unuon, но тогда теряется текущий степ. Или после джойна в рамках строки как-то найти последнее заполненное поле.
🤩 Any ideas?
У нас есть три вьюшки с id и json-полем. Вьюшки собираются по разным фильтрам.
для id = 1: [json]
для id = 2: [default_json, json]
для id = 3: [default_json, default_json, json]
и т.д.
При этом в default_json прокидывается текущий степ, поэтому нам нужно не потерять это название.
- делаем full join
- делаем unpivot
- добавляем флаг is_missed на основе null
- итерируемся с конца в рамках id и удаляем все is_missed = 1, пока не найдём is_missed = 0
Лично мне это кажется слишком громоздкий и малочитаемым, поэтому хочется двинуться в сторону unuon, но тогда теряется текущий степ. Или после джойна в рамках строки как-то найти последнее заполненное поле.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5⚡1
На этих выходных я сходила на сходку аналитиков, где мы пообщались на разные темы и поделились своими мнениями.
Потом обсудили несколько резюме. На всякий случай я писала заметки себе на будущее, и вот что туда попало:
- что делал
- чем делал (инструменты)
- какая была цель
- какой результат и вэлью
Результатом может быть увеличение хорошей метрики, уменьшение плохой метрики или стабилизация/сохранение какой-то метрики.
Я сформулировала это так: все continuous задачи перевести в done.
Обсудили свои планы, идеи, решения, что я прямо замотивировалась встать и начать делать!
Всего мы просидели 6 часов, но я немного огорчилась, что так мало!
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19❤9❤🔥4💯2
Логика с json'ами
На прошлой неделе я вкидывала задачу. Мы ещё раз пообсуждали и вот на чем остановились:
1️⃣ Делаем фулл джойн исходных витрин: view1, view1_1, ...
Идею с кросс джойнами мы решили оставить)
2️⃣ Делим фулловую таблицу на n вьюшек, где n - это количество шагов. Начинаем с конца (последнего заполненного).
Пример:
when step1_2 is not null => v_step1_2 - новая вьюшка для строк, у которых есть степ1_2:
3️⃣ Делаем left anti join фулловой таблицы с созданной вьюшкой, получаем строки, которые не вошли:
Повторяем шаги 2 и 3 n раз.
NB! В следующих вьюшках количество столбцов уменьшается (исключаем уже выделенный степ)
1) when step1_1 is not null => v_step1_1
После left anti join обновленная фулловая:
На последнем этапе просто берем id и первый столбец.
Итак, у нас 3 вьюшки с разным количеством столбцов.
️4️⃣ Делаем coalesce(stepn, default_json)
5️⃣ Делаем array(всех шагов) => получаем одинаковую структуру для всех вьюшек с полями id и array
6️⃣ Union
🕺 🕺 🕺 🕺 🕺 🕺 🕺
На прошлой неделе я вкидывала задачу. Мы ещё раз пообсуждали и вот на чем остановились:
Идею с кросс джойнами мы решили оставить)
Пример:
when step1_2 is not null => v_step1_2 - новая вьюшка для строк, у которых есть степ1_2:
3 null null json
5 json null json
6 null json json
7 json json json1 json null null
2 null json null
4 json json null
Повторяем шаги 2 и 3 n раз.
NB! В следующих вьюшках количество столбцов уменьшается (исключаем уже выделенный степ)
1) when step1_1 is not null => v_step1_1
2 null json
4 json json
После left anti join обновленная фулловая:
1 json null nullНа последнем этапе просто берем id и первый столбец.
Итак, у нас 3 вьюшки с разным количеством столбцов.
️
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯8🔥3🆒3
Написала статью про планы запросов!
Пару месяцев лежала в бэклоге, месяц собиралась в голове, 3 дня писалась, и теперь она здесь)
Сесть и сделать сподвигла последняя дз по курсу амбассадоров. Там был выбор между статьёй и подкастом. Но до подкастов я как-нибудь тоже доберусь)
https://habr.com/ru/articles/807421/
Пару месяцев лежала в бэклоге, месяц собиралась в голове, 3 дня писалась, и теперь она здесь)
Сесть и сделать сподвигла последняя дз по курсу амбассадоров. Там был выбор между статьёй и подкастом. Но до подкастов я как-нибудь тоже доберусь)
https://habr.com/ru/articles/807421/
Хабр
Spark. План запросов на примерах
Всем привет! В этой статье возьмем за основу пару таблиц и пройдемся по планам запросов по нарастающей: от обычного селекта до джойнов, оконок и репартиционирования. Посмотрим, чем отличаются виды...
🔥26❤🔥5 4
Теория или практика?
📖 Наконец-то прочитала книжку "Spark в действии". Очень понравился вот этот рисунок: он супер понятно описывает суть ленивых вычислений) Spark копит все преобразования над данными, пока что-то не заставит его запустить весь пайплайн (например, show).
Отметила для себя пару новых моментов:
1️⃣ Можно создать табличку через sql и сразу перевести её в датафрейм (я думала, что такое работает только для реальных таблиц)
Например:
2️⃣ Есть интересные методы сортировки asc_nulls_first, asc_nulls_last (для desc так же), чтобы обозначить порядок для нуллов
🐰 Ещё позабавили некоторые формулировки)
Надеюсь, что это трудности перевода))
🐱 Вообще пришло осознание, что теоретические книжки легко читаются, когда ты уже пощупал это на практике.
А вы как считаете, когда нужно читать умные книжки?
#spark
Отметила для себя пару новых моментов:
Например:
spark.sql(
'select id from users'
) \
.createOrReplaceTempView('view_users')
df_users = spark.table('view_users')
"Агрегации - ... в известной степени приближение к методам машинного обучения и искусственного интеллекта".
"Во время моей работы со Spark я встречал два типа людей: тех, кто имел опыт работы с Apache Hadoop, и тех, у кого не было такого опыта".
Надеюсь, что это трудности перевода))
А вы как считаете, когда нужно читать умные книжки?
#spark
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17 8❤🔥4
Репликация табличек
👫 Кратко про стек
clickhouse - это база данных))
airflow - оркестратор)
dbt - тулза для удобной работы с трансформацией данных, контроля их качества, ещё позволяет все DDL делать через селекты
💐 Кейс
Недавно у нас данные в кликхаусе переехали на новый кластер с поддержкой репликации. А поверх этих данных крутились пайплайны в airflow и запускались проверочки на dbt. И в один момент все упало😐
Что ж, надо фиксить. Самая большая боль - это как поднять упавшие dbt модельки, которые писали данные в таблички. Например, есть такие, которые каждый день собирают количество строк в данных для мониторинга.
Пошел пул проблем:
🔴 откуда берутся таблички с суффиксами dbt_backup, dbt_tmp_tables, dbt_new_data и почему они затирают оригинальные
🔴 почему инкрементальные модельки (которые дописывают порцию данных) не могут это делать при повторных запусках
🔴 как создавать таблички из csv файликов с движками Replicated
🔴 почему вдруг я не могу запускать больше 5 параллельных тасок в даге и как это исправить
🔴 нет грантов на операцию sync replica
🔴 почему при чтении одной и той же таблицы то 100 строк, то 0
...
Задала вопрос в сообществе dbt в слаке, и там один чел прокомментил, что столкнулся с теми же самыми проблемами. Совпадение? (он из WB)
В общем, это всё удалось решить так:
⭐️ в dbt обязательно прописывать в конфигах cluster (спец. штука для реплицированных таблиц)
⭐️ для csv файликов тоже в конфигах можно прописать дефолтный движок
⭐️ для параллельного запуска тасок есть параметр max_active_tasks
⭐️ перепроверить, что в коде с модельками и сами таблички заданы через Replicated
Многие проблемы решились последним пунктом, в том числе с 0 строк. Тут суть в том, что когда создается стандартная табличка (с движком без Replicated), то она находится на одной ноде. Но когда мы запросом туда стучимся, то нас могут отправить на другую ноду, где этих данных нет👍
А вы работали с репликацией, есть запомнившаяся мудрость на будущее?
P.S. все, идите отдыхайте😶 🐱 🐱
clickhouse - это база данных))
airflow - оркестратор)
dbt - тулза для удобной работы с трансформацией данных, контроля их качества, ещё позволяет все DDL делать через селекты
Недавно у нас данные в кликхаусе переехали на новый кластер с поддержкой репликации. А поверх этих данных крутились пайплайны в airflow и запускались проверочки на dbt. И в один момент все упало
Что ж, надо фиксить. Самая большая боль - это как поднять упавшие dbt модельки, которые писали данные в таблички. Например, есть такие, которые каждый день собирают количество строк в данных для мониторинга.
Пошел пул проблем:
...
Задала вопрос в сообществе dbt в слаке, и там один чел прокомментил, что столкнулся с теми же самыми проблемами. Совпадение? (он из WB)
В общем, это всё удалось решить так:
Многие проблемы решились последним пунктом, в том числе с 0 строк. Тут суть в том, что когда создается стандартная табличка (с движком без Replicated), то она находится на одной ноде. Но когда мы запросом туда стучимся, то нас могут отправить на другую ноду, где этих данных нет
А вы работали с репликацией, есть запомнившаяся мудрость на будущее?
P.S. все, идите отдыхайте
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11 10⚡6
С одним из подписчиков обсуждали рабочую задачку, накидали варианты. Сейчас я к ней вернулась, и у меня созрело финальное решение)
На фронте есть табличка с именами и датами, по которой есть поиск. Поиск нужен по столбцу дат. Поисковой запрос идёт на бэк, и грузятся данные из бд.
Дата в формате mm/dd/yyyy: 05/04/2024 = 04.05.2024. В бд как обычно: 2024-05-04.
Примеры
Вывод:
Вывод:
Предложить наиболее эффективный вариант поиска.
Какие идеи?
Please open Telegram to view this post
VIEW IN TELEGRAM