uz
Feedback

Firibgarlarga uchmang! Telemetrio bunday kanallarni topadi va belgilaydi 👉 Belgini ko‘rmoqchi bo‘lsangiz, obuna bo‘ling

дата инженеретта

дата инженеретта

Kanalga Telegram’da o‘tish

мелкое — крупно, в глубоком разговоре мудрость приходит по вопросам сюда: @aigul_sea

Ko'proq ko'rsatish
3 436
Obunachilar
-224 soatlar
-27 kun
+330 kun
Postlar arxiv
Рынок ИИ в России быстро растёт: по предварительным оценкам, в 2025 году его объём достиг $2,1 млрд, а спрос на ML-инженеров
Рынок ИИ в России быстро растёт: по предварительным оценкам, в 2025 году его объём достиг $2,1 млрд, а спрос на ML-инженеров уже сейчас опережает предложение. Бизнесу нужны специалисты для реальных задач — от рекомендательных систем и аналитики до автоматизации сложных процессов. На курсе "Инженер машинного обучения с нуля" в Нетологии делают упор на практических навыках. Вы научитесь работать со всем циклом ML-разработки: • формулировать и проверять гипотезы с помощью статистики; • создавать и дообучать нейросети, использовать transfer learning; • собирать ETL-пайплайны и готовить данные; • контейнеризировать проекты и настраивать CI/CD для ML-систем. В программе больше 10 проектов для портфолио, задачи от реальных компаний и шанс на стажировку в Globus IT. А эксперты из Яндекса, Сбера и Amazon помогут на протяжении всего обучения. Начните свой путь в профессию, которая уже меняет рынок. Получите скидку 45% по промокоду ML2026 с возможностью оформить рассрочку. Реклама. ООО “Нетология” ОГРН 1207700135884 Erid: 2VSb5xADXus

Repost from БАШНЯ
HARD SKILLS🫥 Сегодня разбираем реальный кейс о том, как один файл и смена инфраструктуры положили Nexus и остановили релизы�
+4
HARD SKILLS🫥 Сегодня разбираем реальный кейс о том, как один файл и смена инфраструктуры положили Nexus и остановили релизы👩‍💻 Делитесь этим постом с друзьями и пишите свои вопросы в комментарии ✍️ Автор поста: @data_engineerette #hardskills

Поделилась тут интересной историей🤗

Замена show partitions Часто бывает, что нужно найти последнюю партицию и начать грузить данные со следующей. Пройдемся от банальных вариантов до особенно интересных 1️⃣ max(date) - самое ресурсозатратное, потому что нужно пробежаться по всей таблице 2️⃣ show partitions - отличный способ, пробегаемся только по метаданным Другие 2 варианта подойдут для айсберга: 3️⃣ raw.my_table.partitions - в айсберге есть много системных мета-таблиц, таблица с партициями выглядит так:
-RECORD 0-------------------------------------------
 partition                     | {2025-03-29 00:00:00}   
 spec_id                       | 0                       
 record_count                  | 7251                    
 file_count                    | 1                       
 total_data_file_size_in_bytes | 91062                   
 position_delete_record_count  | 0                       
 position_delete_file_count    | 0                       
 equality_delete_record_count  | 0                       
 equality_delete_file_count    | 0                       
 last_updated_at               | 2025-11-20 12:25:48.678 
 last_updated_snapshot_id      | 5910543042911865752     
only showing top 1 row
Это как аналог show partitions: идем в табличку и отбираем max(partition) 4️⃣ TBLPROPERTIES - тут обсудим подробнее Пусть таблица партицируется по другим полям или не партицируется вообще. Тогда в момент загрузки можно проставить любое свойство:

ALTER TABLE raw.my_table
SET TBLPROPERTIES ('raw.last-date' = '2025-12-05');
Их может быть несколько, посмотрим на текущий список:

SHOW TBLPROPERTIES raw.my_table
Сюда добавилось наше кастомное свойство:
+-------------------------------+-----------------+
|key                            |value            |
+-------------------------------+-----------------+
|current-snapshot-id            |63675018113182479|
|format                         |iceberg/PARQUET  |
|format-version                 |2                |
|raw.last-date                  |2025-12-05       |
|write.format.default           |PARQUET          |
|write.parquet.compression-codec|zstd             |
+-------------------------------+-----------------+
Убрать свойство можно так:

ALTER TABLE raw.my_table
UNSET TBLPROPERTIES('raw.last-date');
Каждое изменение свойства будет создавать новый файл с метой - а это доп расходы на хранение и куча разных версий одной и той же таблицы. Поэтому сначала проанализируйте, какой метод будет подходить именно для ваших данных и ресурсов @data_engineerette

Lakehouse для аналитиков и инженеров данных Изучи набирающий популярность подход к построению хранилищ данных Data Lakehouse
Lakehouse для аналитиков и инженеров данных Изучи набирающий популярность подход к построению хранилищ данных Data Lakehouse c разделенным Compute и Storage на основе Iceberg и Trino. 🌐 В программе курса: ▪️Современная архитектура аналитических систем от DWH и Data Lake до Lakehouse с разделением Compute и Storage на базе Apache Iceberg и Trino. ▪️Iceberg: управление файлами, снимками, каталогами, схемами изменений и очисткой. ▪️Практическое использование Iceberg Catalog, работа с кластером Trino (на Kubernetes), подключение данных на S3 и выполнение SQL/​Python-запросов. ▪️Работа с Iceberg+Trinо на больших масштабах: сложные запросы к датасету TPC-DS (2.8 млрд строк), интеграция с DBT, Apache Airflow, оценка производительность систем. ▪️Построение пайплайнов, инструменты для корректной поддержки, обновления и масштабирования Lakehouse-инфраструктуры на уровне предприятия. 🥸 Кто мы: R&D-центр Devhands.io, наш канал. Автор курса — Алексей Белозерский, руководитель направления Big Data Services в компании VK Tech. 🗓 Старт курса: 5 февраля, 18:00, 6 недель обучения. Изучить программу и записаться можно здесь. Ждем вас! Реклама. ИП Рыбак А.А. ИНН 771407709607 Erid: 2Vtzqwgrf3y

Двойные эмоциональные качели Эта история случилась, которая я устраивалась в Сбер. И до сих пор только избранные знали, как э
+1
Двойные эмоциональные качели Эта история случилась, которая я устраивалась в Сбер. И до сих пор только избранные знали, как это произошло на самом деле) 🐌 Я параллельно общалась с двумя компаниями: первая удаленно (Mediascope), вторая в мск (Сбер) Особенности первой позиции: удаленно, зп в 2 раза больше, да на стыке с де, есть ночные дежурства, после которых можно начать попозже Особенности второй позиции: надо переезжать, зп в 3 раза больше, крутой вайб с лидом, чисто де задачи. Что меня больше всего впечатлило - лид попросил глянуть тестовое и самой написать, сколько времени понадобится на выполнение. Почему-то этот момент попал мне в самое сердечко💖 Мне очень понравилась вторая позиция, но было сильно давление сверху от мамы. Типо вот так возьму и оставлю ее одну... 🧐 Именно тогда я вступила датаинженерские чатики, чтобы поспрашивать, стоит ли переезжать, сколько стоило просить, как работается. Нашла похожий вопрос на хабре Q&A и написала автору на почту. Писала людям на линкедине из этих компаний, спрашивала про общее ощущение, про задачи. Даже нашла девчонку, которая до этого работала в моей текущей команде и увольнялась по тем же причинам, что и я)) В общем, скрепя сердце я приняла свою долю, отказала сберу и решила согласиться на удаленку в предстоящем вечернем созвоне. Но мне воткнули нож в спину, еще вчера они переманивали к себе, а уже сегодня выбрасывают на улицу🥲 Ничего не оставалось, как попытаться стереть память hr 🏃‍♂️А дальше я уволилась, в тот же вечер села в поезд, с утра приехала в мск, съемной квартиры еще нет, оставила чемоданы и сумки на вокзале, на улице снег и минусовая температура, в пальто и демисезонных сапогах очень холодно, оформилась только к вечеру, успела на ежеквартальный фуршет... А там мне сказали: "Мы тебя так ждали"💖 Happy end🎉 P.S. Мои переписки в датаинженерских чатиках, сомнения в переезде и обсуждения зп читал мой будущий лид. Я видела наши общие каналы, но понадеялась, что нормальные люди не мониторят там сутками) Спустя полгода сидя в ресторанчике, он мне все это рассказал👀 И что они в команде это тоже обсуждали. Я готова была провалиться сквозь землю @data_engineerette

Удаляем дубли в ClickHouse без ReplacingMergeTree У меня была задачка настроить создание табличек через фреймворк. И вот настал момент - локально все работает, доступ к кх я получила, джобку доделана. Пора тестить! 💻 Сначала я решила покрутить запросы ручками, проверить права на создание табличек, все ли работает. Создаю на движке MergeTree, пишу данные - все ок. Перехожу к ReplicatedMergeTree - создаю табличку, вставляю пару строк данных, делаю select...

CREATE TABLE db.test_table_local ON CLUSTER '{cluster}'
(
    `id` UInt32,
    `name` String
)
ENGINE = ReplicatedMergeTree
ORDER BY id;

INSERT INTO db.test_table_local
VALUES (1, 'test');
INSERT INTO db.test_table_local
VALUES (1, 'test');

SELECT * FROM db.test_table_local;
Нет, что-то не то. Я вставила 2 строки, но вижу одну. Почему? В табличке всего 2 поля, что пошло не так? 😑 Иду искать проблему. Попробовала вставить еще раз и еще раз, посмотрела в system.parts на незавершенные мутации, сделала SYSTEM SYNC REPLICA, но ничего не помогло Потом я поняла, что удаляются дубликаты для записей с одним первичным ключом. Но в кх же нет такой строгости? Что-то не сходится Нахожу в доке по кх:
Для движков *ReplicatedMergeTree дедупликация вставок включена по умолчанию и управляется настройками replicated_deduplication_window и replicated_deduplication_window_seconds. Для нереплицируемых движков *MergeTree дедупликация управляется настройкой non_replicated_deduplication_window.
Иду в табличку смотреть эти настройки:

SELECT * FROM system.merge_tree_settings
WHERE name LIKE '%deduplicat%';
Из основных настроек вижу: 📌non_replicated_deduplication_window = 0, поэтому в MergeTree данные вставляются как обычно 📌replicated_deduplication_window != 0, дубликаты не вставляются, они проверяются по хэш-суммам для определенного количества свежих блоков (по дефолту 10к), хэши лежат в Zookeeper 📌replicated_deduplication_window_seconds - сколько секунд хранятся эти хэш-суммы (по дефолту 3600с = 1ч) Я со своей задублированной строкой попала сразу в 2 настройки. До этого не замечала такого поведения в кх, хотя это дефолтное🤷‍♂️ Зато узнала про существование таблицы system.merge_tree_settings @data_engineerette

Кастомизируем Spark UI Когда работают джобки в спарк приложении, мы обычно видим только техническое описание. Но есть возможн
Кастомизируем Spark UI Когда работают джобки в спарк приложении, мы обычно видим только техническое описание. Но есть возможность написать что-то читаемое:

spark.sparkContext.setJobDescription(s"Merge into ${schema}.${table}")

spark.sql(mysql)

spark.sparkContext.setJobDescription("Count deleted rows")

df.filter(col("is_deleted") === true).count()
Если не менять описание, то все экшены будут подтягивать последнее Вернуть к дефолтным можно так:

spark.sparkContext.setJobDescription(None)
На вкладке SQL все это тоже отображается @data_engineerette

Баг/фича в DBeaver Вы когда-нибудь пробовали заполнить поле с датой значением 9999-12-31 23:59:59.000 +0300? Если зайти в нас
Баг/фича в DBeaver Вы когда-нибудь пробовали заполнить поле с датой значением 9999-12-31 23:59:59.000 +0300? Если зайти в настройки и поменять на таймзону дальше мск, то мы будем уже в 10000м году Даже есть такая штука, как Y10K problem - проблема 10000го года. ПО может поломаться, поля переполниться, поэтому люди задумываются уже сейчас о введении дополнительного нуля, чтобы различать 02025 и 12025 А еще ближе становится Y2038 problem. Тогда unix timestamp перестанет помещаться в int, и 2038 год превратится снова в 1901. Поэтому в этом случае пора переходить на bigint, пока не поздно @data_enigineerette

Новые требования к кандидатам в 2026? Мне периодически пишут hr и иногда я отвечаю, чтобы быть в курсе текущих трендов на рын
Новые требования к кандидатам в 2026? Мне периодически пишут hr и иногда я отвечаю, чтобы быть в курсе текущих трендов на рынке. Из последних новостей - рекрутинговая компания пошла согласовывать резюме с компанией-заказчиком, но они требуют не меньше двух лет на последнем месте А недавно моему знакомому разрабу после хорошего собеса отказали в оффере, потому что не было диплома о высшем образовании Получается, перейти все сложнее, войти еще сложнее, а попасть под волну сокращения проще простого?

Мои итоги 2025 года 🙂 Нагенерила какую только можно стату по каналу. По точным показателям выросли все метрики ехуу🙂 От ииш
+2
Мои итоги 2025 года 🙂 Нагенерила какую только можно стату по каналу. По точным показателям выросли все метрики ехуу🙂 От иишки же мне понравилось, как она выделила ключевые слова и сформулировала позиционирование канала, возьму себе на заметку) Итак, за этот год вас стало в 2 раза больше! Надеялась, что до нг наберем 3к, но так уж и быть, добъем в следующем году! Пробежимся по основым циферкам: 🌲 30102 музыкальные минуты 🌲 1278 выполненных личных задач 🌲 210 часов в поездах 🌲 85 культурно-развлекательных мероприятий 🌲 65 закрытых рабочих задач 🌲 53 посещения врачей 🌲 25 просмотренных фильмов и сериалов 🌲 20 митапов 🌲 19 поездок 🌲 7 прочитанных книг 🌲 6 городов 🌲 2 пройденных курса 🌲 1 проведенный вебинар Хотелось бы отдельно отметить пункт про вебинар - это был мой первый публичный спич на такую аудиторию, и все прошло блестяще! а еще: 🏡 перешла из Сбера в Ламоду и благодарна как прошлым тиммейтам, так и действующим 🌸 прошла курс по управлению командой и заложила ростки для будущего ☕️ съездила на смартдату и хорошенько понетворкалась По традиции сделала подборочку постов: 😎 Топовые Как я стала lamodian Стата по моим офферам Как хранятся айсберг таблицы Мелкие файлы на практике 🙂 Мемные Когда тимлид смотрит твои сторис Хокку про DE 🥰 Сложные Газлайтинг движков Sort-Merge Join без шафла Коммитеры в Spark Preemption в YARN По подписчикам для мерча пришел всего 21 человек, но они расщедрились и решили 2-3 места тоже наградить мини-наборами, так что я в плюсе! Спасибо всем, кто откликнулся❤️ Прошлогодний обзор можно посмотреть тут ❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ А я поздравляю вас всех с наступающим новым годом! 🥳 Пусть каждое дело завершается со статусом success, здоровье backfill-ится за предыдущие периоды, доходы растут как в SummingMergeTree, а partitioning помогает отделять важное от суеты! И пусть даже самый сложный путь к цели сократится до O(1)!🎄 @data_engineerette

Подводим итоги! ➡️ Летом этого года нашла такую штуку, как "YearCompass". Это док для подведения итогов года. Там есть вопросы про предыдущий 2025 год - что произошло, какие достижения и уроки. И про наступающий 2026 - про мечты, привычки и планы Я хочу попробовать и посидеть перед нг. Хотя не очень люблю рефлексировать, многое вообще забываю, а некоторые желания у меня повторяются из года в год с 14 лет🙂 📌 На сайте можно скачать в цифровом или бумажном формате на любом языке. Я же прикрепила цифровую версию, которую можно заполнить на любом устройстве ❄️❄️❄️❄️❄️ Адвенты тоже закончились!🥳 В последний день нужно было объединить 2 таблички, где одна из табличек имела приоритет. Рассказали про конструкцию insert into on conflict do nothing. Я же сделала через union all, добавила новый столбец 1 as ordering и засунула в оконку:

row_number() over(partition by system_id order by dispatched_at desc, ordering)
🏴󠁧󠁢󠁥󠁮󠁧󠁿 Фразы дня dispatch ledger - журнал отправлений edifying - поучительный eerie calm - жуткое спокойствие it's a wrap - снято/все закончили network hiccup - сетевой сбой perfect liftoff - идеальный запуск pumped - воодушевлен with any luck - если повезет ✨Advent of SQL (с впн) ✨SQL Advent Calendar (с впн) ✨Мои решения Ну, а я с этого момента уже в предновогоднем отпуске! Еще подготовлю отдельный пост с итогами года @data_engineerette

Advent of SQL. Days 11-14 🏂 Сначала вспомнили про скользящее среднее, его нужно было найти за 7 предыдущих дней. Для этого есть конструкция rows between:

avg(score) over (
  partition by child_id order by behavior_date
  rows between 6 preceding and current row
) as avg_rolling_7_days
Я про нее писала в начале года, но к этому моменту все равно забыла, что можно циферками задавать промежуток) Дальше задачка на полнотекстовый поиск, такого я не ожидала😁 По итогу познакомилась с несколькими функциями и операторами: to_tsvector to_tsquery ts_rank setweight @@ Потом пошли парсить xml и считать количество зарегавшихся пассажиров. Автор использовал cross join lateral, ну а я нашла другой способ, он мне нравится больше:

cardinality(xpath('/manifest/passengers/passenger', manifest_xml)) as passengers_count
В предпоследний день искали пути от одной точки до другой и задействовали recursive cte Ну вот и почти все! Сегодня будет последнее задание 🥲 🏴󠁧󠁢󠁥󠁮󠁧󠁿 Фразы дня barrel straight down the hill - нестись вниз по склону circuitous path - окольный, окружной путь mind-bending - сложный schlep - волочиться winding route - извилистый маршрут 📍 Advent of SQL (с впн) 📍 SQL Advent Calendar (с впн) 📍 Мои решения @data_engineerette

Собрались как-то DeepSeek, Grok и Gemini... Вам попадался видос, как несколько иишек играют в мафию? Я наконец посмотрела, и
Собрались как-то DeepSeek, Grok и Gemini... Вам попадался видос, как несколько иишек играют в мафию? Я наконец посмотрела, и тут прям полноценный разбор, как каждая модель себя ведет. Кто-то более официозно, кто-то льет много воды, кто-то умеет строить хитрые планы, а кто-то не понял правила игры 😁 А на этом канале автор выкладывает игры полностью. Обязательно хочу посмотреть игры целиком и проследить, как у них проявляются персональные характеристики 😮

Advent of SQL. Day 10 🏰 Вот такую конструкцию я 200% ни разу не встречала и не подозревала о ней! В задаче нужно было перенести данные из таблицы1 в таблицу2 и вывести только перенесенные строчки. Но обязательно в одном запросе - эммм... а как? Дали подсказку - использовать по максимуму возможности постгри. Что ж, по первой ссылке я нашла тред на stackoverflow С помощью CTE и RETURNING можно возвращать вставленные/удаленные/обновленные строки и передавать их в следующий запрос. Наверное, можно навешивать несколько cte, строить цепочки таких перемещений и даже ETL из raw в витрину, но звучит как мазохизм 😁 В финальном запросе получилось так:

with moved_rows as (
  delete from deliveries
  where ...
  returning *
)
insert into misdelivered_presents
select
  *,
  date_trunc('second', LOCALTIMESTAMP) as flagged_at,
  'Invalid delivery location' as reason
from moved_rows
returning *
Мы из delete передаем строки в insert, а из insert выводим на экран - это мэджик какой-то 😍 🏴󠁧󠁢󠁥󠁮󠁧󠁿 Фразы дня I'm feeling stingy - ощущаю себя скупым inexplicably - необъяснимо issue an edict - издать указ meddle in - вмешиваться muck it up - все испортить plop - плюхнуться sleigh is airborne - сани находятся в воздухе volcano rim - край вулкана 📍 Advent of SQL (с впн) 📍 SQL Advent Calendar (с впн) 📍 Мои решения @data_engineerette

Advent of SQL. Day 9 🗓️ День 9: нужно вытащить из вложенного json нужные поля. Я так и не могу запомнить, как правильно это делается в постгре, поэтому делала по интуиции) Заодно познакомилась с новыми функциями Как получилось у меня:

select
  order_data['gift']['wrapped']::boolean as gift_wrapped,
  trim(both '"' from order_data['risk']['flag']::text) as risk_flag
from orders
Я сделала в питонячем виде, и это сработало👍 Сначало было просто order_data['risk']['flag'], но мне не понравились лишние кавычки:
risk_flag
----------
"high"
"medium"
Перепроверила типы данных через pg_typeof. В первом случае тип столбца jsonb, а во втором - text:

select
  pg_typeof(order_data['risk']['flag']) as risk_flag,
  pg_typeof(order_data['risk']['flag']::text) as risk_flag2
from orders
Я кастанула, но кавычки не ушли. Пошла гуглить, наверняка есть хитрый trim без substring/replace. И такой есть! Вот эта прикольная конструкция позволяет нам удалять символы с разных сторон, общий синтаксис такой: TRIM([LEADING | TRAILING | BOTH] trim_character FROM source_string) У спикера же получилось более канонично 🙂

select
  (order_data -> 'gift' ->> 'wrapped')::boolean as gift_wrapped,
  order_data -> 'risk' ->> 'flag' as risk_flag
from orders
-> достает по ключу json ->> достает по ключу строку 📍 Advent of SQL (с впн) 📍 SQL Advent Calendar (с впн) 📍 Мои решения @data_engineerette

Хотите побыть Дедом Морозом? Новый год - это пора чудес✨ И сегодня вы можете помочь исполнению новогоднего чуда! У нас в ламоде проводится конкурс мерча. И если вы хотите, чтобы его получила я - то буду благодарна за вашу подписку 🙂🙂 А вообще в канале рассказывается много чего интересного: 🤩статьи на хабре 🤩записи с выступлений 🤩внутренние новости 🤩карточки с полезностями 🤩мемасики 🤩а также проводятся новогодние розыгрыши - сейчас есть активный до 22го декабря🎄

Advent of SQL. Days 7-8 ☕️ На 7й день мы распределяли посетителей по разным какао-станциям на основе их вкусовых предпочтений. Для этого нужно было вспомнить про пересечения и агрегацию массивов Получилось такое условие джойна, оно возвращает true, если массивы пересекаются:

left join available_cocoa_cars c
  on p.favorite_mixins && c.available_mixins
А так можно красиво собрать все доступные какао-станции по каждому посетителю. Про сортировку даже не вспомнила, что ее можно туда засунуть:

select
  passenger_name,
  array_agg(c.car_id order by c.car_id)
from ...
group by passenger_name
🌄 На 8й день произошло целое открытие для меня. Все это время существовала концепция named window, а я ни разу ее не видела??😱 Мы определяем окно в самом конце запроса типо как cte и можем переиспользовать название окна в расчетах столбцов:

select
  product_id,
  price as product_price,
  lead(price) over w as previous_price,
  row_number() over w as rn
from price_changes
window w as (
  partition by product_id order by effective_timestamp desc
)
Причем этот синтаксис работает просто везде: PostgreSQL, MySQL, ClickHouse, Spark SQL, Oracle, Vertica... Что? 😍 Почему это так удобно, но нигде не используется? 📍 Advent of SQL (с впн) 📍 SQL Advent Calendar (с впн) 📍 Мои решения

Advent of SQL. Days 5-6 На пятой задаче было топ-3 через row_number и cte - мы с подобной штукой уже встречались ранее:

row_number() over(partition by user_name order by count(1) desc) as rn
😇Но на 6й день я немного потерялась... Долго не могла понять суть задачи) Вот есть таблица с датами отправки подарков и надо найти даты, на которые забыли записать доставку подарков. Но откуда я должна взять даты, которых нет?? Перечитала summary дважды и посмотрела дважды видос. Решила послушать подсказку - спикер посоветовал использовать "эзотерический" джойн. И почему моя первая мысль была про asof join, я даже пошла гуглить примеры 😁 Потом решила, что не может быть такого задания, когда в предыдущем мы всего лишь применяли оконку🥺 В итоге формула решения такая: generate_series + cross join + left join 📍 Advent of SQL (с впн) 📍 SQL Advent Calendar (с впн) 📍 Мои решения

Advent of SQL. Day 4 Задачка на приведение данных к единому формату и применение like, ilike, case when, union В одном из case мне нужно было сделать assigned_task ilike '%snow%' or assigned_task ilike '%shovel%', но это так скучно)) Поэтому я пошла гуглить другие варианты, нашла такие:

where assigned_task ~* 'snow|shovel'

where lower(assigned_task) similar to '%(snow|shovel)%'

where assigned_task ilike any (array['%snow%', '%shovel%'])

where assigned_task ilike any('{%snow%,%shovel%}')
Раньше я пользовалась только ~~ вместо like. Но оказалось, для остальных тоже есть свои символы. not ilike - это вообще что за демон?
like        ~~
ilike       ~~*
not like    !~~
not ilike   !~~*
А также я узнала нагуглила функцию initcap. В одной из таблиц данные уже были в едином формате, их нужно было привести к другому: stage_setup -> Stage Setup. initcap как раз делает то, что нужно: она каждое слово в строке пишет с заглавной буквы:

select initcap(replace(role, '_', ' ')) as role
🏴󠁧󠁢󠁥󠁮󠁧󠁿 Фразы дня wonky list/space - кривой список/пробел volunteer roster - список/расписание волонтеров handwarmer handout - раздача грелок для рук studly case = pascal case = StudlyCaps - название в формате MyClassName strong suit - сильная сторона В конце спикер попросил рассказать о челлендже своим друзьям. И своим врагам тоже 😁 📍 Advent of SQL (с впн) 📍 SQL Advent Calendar (с впн) 📍 Мои решения @data_engineerette