NULL++
93 subscribers
49 photos
16 links
Канал для тех, кто хочет развиваться как Data Analyst, Data Engineer и BI-Analyst
@HexMikhail
Download Telegram
Сегодня я хочу рассказать, а кому-то просто напомнить, о поведении NULL при вычислении логических операций. Рассмотрю эти операции на примере PostgreSQL, но логика стандартна для большинства СУБД.
Как видите, результат выполнения логической операции не всегда будет NULL.
А последний пример, когда NOT NULL в результате даёт NULL, сломал мне мозг в своё время)

@nullpp #NULL #SQL #PostgreSQL
👌2🤷‍♀1
Продолжим интересности с NULL? =) В данных выражениях, я думаю, первые пять вообще не выбиваются из обычной логики.
А вот выражение NULL IS DISTINCT FROM NULL очень интересное. В некоторых случаях имеет смысл написать строка IS DISTINCT FROM NULL или строка IS NOT DISTINCT FROM NULL, чтобы просто проверить, равно ли NULL всё значение строки, без каких-либо дополнительных проверок полей строки. А так как выражения IS всегда возвращают TRUE или FALSE и никогда NULL даже с операндом NULL они интерпретируют значение как неизвестное логическое состояние и выдают в первом случае FALSE, а во втором TRUE.

@nullpp #NULL #SQL #PostgreSQL
🤷‍♀1
Подумал и решил рассмотреть последние два примера из предыдущего поста более подробно.
Выражению a IS DISTINCT FROM b соответствует такое вот длинное выражение a <> b OR (a IS NULL) <> (b IS NULL).
Аналогично, a IS NOT DISTINCT FROM b соответствует выражению a = b OR (a IS NULL) = (b IS NULL).
Теперь если вместо a и b подставить значения NULL, то всё встанет на свои места =)
Но в каких случаях применяются данные конструкции? Вот пример использования:
SELECT * FROM Table WHERE id IS DISTINCT FROM 17;

Результаты исключают все строки, в которых id совпадает со значением 17. Чем же такой запрос будет отличаться от простого WHERE id <> 17?
Подсказка: вся разница в NULL-значениях в результате запроса.

@nullpp #NULL #SQL #PostgreSQL
🤷‍♀1🔥1
Всем привет!
Когда я делал свой дипломный проект и арендовал виртуальный сервер, при первичной настройке выполнения скриптов по расписанию, я не мог понять почему они не выполняются в нужное время.
Мне подсказали, что нужно бы проверить таймзону самого сервера - и действительно, оказалось, что она была UTC+0 вместо привычной для меня UTC+3. Это я к чему?
К тому, что у СУБД таймзона может как совпадать с сервером, так и отличаться. Да и вообще, при работе с датой-временем надо иметь в виду, что таймзоны могут повлиять на результаты не только работы, но и аналитических выводов, которые можно получить, если мы неправильно их будем интерпретировать из-за этого.
В PostgreSQL есть два основных типа для работы со временем:
- TIMESTAMP(или TIMESTAMP WITHOUT TIME ZONE) - хранит только дату и время, без привязки к часовому поясу. Это просто число, означающее "настенные часы в определённый момент". При сохранении 2023-10-25 15:30:00 база не знает, было это в Лондоне, в Москве или в Токио.
- TIMESTAMPTZ (или TIMESTAMP WITH TIME ZONE) - рекомендуемый к использованию тип. Он не хранит пояс отдельно внутри себя. Вместо этого он конвертирует переданное значение в время по UTC (Всемирное координированное время) для хранения. При извлечении данных он преобразует это UTC-время в часовой пояс текущей сессии.
Опять же многое будет зависеть от параметров как на самом сервере, так и от параметров СУБД.
Для определённой сессии можно задать таймзону так:
SET timezone = 'Europe/Moscow';

(кстати, на это нужны определённые права для учётки PostgreSQL.
И при выполнении запросов, например
SELECT doc_dt FROM ticket;

мы получим данные вида 2025-05-12 09:23:48.000 в том случае, если типом поля doc_dt является TIMESTAMP. Впрочем, такой ответ мы получили бы и не устанавливая таймзону перед этим. То есть СУБД принимает "на веру" то, что TIMESTAMP всегда в том часовом поясе, который указан в параметрах.
Мы можем преобразовать таймзону вручную при конкретном запросе (для этого не нужно особых прав):
SELECT doc_dt::TIMESTAMP AT TIME ZONE 'Europe/Moscow' FROM ticket;

В результате получим результат вида: 2025-05-12 09:23:48.000 +0300. Как видите, в самом конце будет указан часовой пояс, причём такой, какой указан в настройках. Точнее, он его просто "припишет".
С TIMESTAMPZ ситуация иначе. Смещение во времени автоматически записывается в БД. И тогда при применении AT TIME ZONE к полю TIMESTAMPZ, он наоборот преобразует в нужный временной пояс.
SET timezone = 'Europe/Moscow';
SELECT doc_dt FROM ticket;

Результат: 2025-05-12 09:23:48.000 +0300
SELECT doc_dt::TIMESTAMP AT TIME ZONE 'Europe/Moscow' FROM ticket;

Результат: 2025-05-12 09:23:48.000 +0300

Сменим таймзону:
SET timezone = 'UTC';
SELECT doc_dt FROM ticket;

Выдаст такой же результат:
2025-05-12 09:23:48.000 +0300


А вот
SELECT doc_dt::TIMESTAMP AT TIME ZONE 'Europe/Moscow' FROM ticket;

Даст нам:
2025-05-12 06:23:48.000 +0300

Как видите AT TIME ZONE - мощный оператор для явного преобразования.
Если применить к TIMESTAMPTZ, он "снимает" пояс и возвращает TIMESTAMP в указанной зоне.
Если применить к TIMESTAMP (без пояса), он "надевает" на него указанный пояс и возвращает TIMESTAMPTZ.

Что делать?
1. Храните всё в UTC. Настройте часовой пояс сервера на UTC. Это стандарт де-факто для backend-разработки и избегает путаницы.
2. Используйте тип TIMESTAMPTZ. Позволяет PostgreSQL делать всю грязную работу по конвертации.
3. Преобразование в локальное время делайте на уровне приложения. Ваше приложение лучше знает, в каком часовом поясе находится пользователь. Передавайте данные в UTC, а финальное отображение делайте на клиенте.

#SQL #PostgreSQL #timezone @nullpp
👍5🤔2
Всем привет!
Я тут немного подумал, чем бы можно было бы разнообразить контент на канале.
Как на счёт того, чтобы выкладывать некоторые задачки (и их решения) на подумать?
Например типа такого:

Задача:
Вывести информацию в какие города можно улететь из Парижа (Paris) и сколько времени это займёт?


Решение в PostgreSQL:
SELECT 
town_to,
TIMEDIFF(time_in, time_out) as flight_time
FROM
Trip
WHERE
town_from = 'Paris';


#Задача #SQL #PostgreSQL #Авиаперелеты
🔥43
Всем привет!
Сегодня будет ещё одна задачка по той же БД

Задача:
Выведите пассажиров с самым длинным ФИО. Пробелы, дефисы и точки считаются частью имени.


Решение будет в первом комменте

#Задача #SQL #PostgreSQL #Авиаперелеты
🔥3
Всем привет!
Хочу немного поговорить сегодня о функции COUNT в SQL. Данную функцию используют для подсчёта количества строк в таблице/вьюшке/результате запроса.

1. Самый простой пример использования - это подсчёт общего количества строк:
SELECT
COUNT(*)
FROM table;

Так можно посчитать все строки, включая те, которые содержат NULL.

2. Если вместо * вставить название колонки:
SELECT
COUNT(col1)
FROM table;

то запрос посчитает количество не-NULL значений.

3. Если нужно посчитать уникальные значения, то внутри нужно добавить DISTINCT:
SELECT
COUNT(DISTINCT col1)
FROM table;

Данный способ работает в PostgreSQL, в других СУБД частенько используются другие функции.

А что, если нам необходимо посчитать количество уникальных строк по двум и более параметрам?
Тут нам поможет функция CONCAT():
SELECT COUNT(DISTINCT CONCAT(col1, ' | ', col2))
FROM table;

- Иногда col1 и col2 нужно привести к формату строки.
- Обычно используют какой-то спецсимвол для соединения, чтобы случайно не пропустить что-нибудь.
Например, если взять просто CONCAT(col1, col2), то конкатенация значений ab и c будет равна конкатенации значений a и bc: abc. То есть DISTINCT решит, что это одинаковые значения.

4. А ещё можно считать количество по условиям:
SELECT 
COUNT(CASE WHEN gender = 'F' THEN 1 END) AS F,
COUNT(CASE WHEN gender = 'M' THEN 1 END) AS M
FROM project_data;

Или вот так тоже можно:
SELECT 
COUNT(*) FILTER (WHERE gender = 'F') AS F,
COUNT(*) FILTER (WHERE gender = 'M') AS M
FROM project_data;


А ещё, нужно помнить, что функция COUNT() является агрегирующей, а это значит, что если мы хотим посчиать количество в разрезе како-нибудь параметра (значений столбца), то надо не забывать про GROUP BY.
В качестве примера, посмотрим распределение покупки товаров по половому признаку:
SELECT 
product_id,
COUNT(CASE WHEN gender = 'F' THEN 1 END) AS F,
COUNT(CASE WHEN gender = 'M' THEN 1 END) AS M
FROM project_data
GROUP BY product_id ;

В результате получим такую таблицу:
product_id|f  |m  |
----------+---+---+
536| 77| 96|
7004| 81| 75|
19812| 73| 79|
47778| 74| 72|
34354| 79| 89|
4035| 80| 82|
44342| 73| 89|
...|...|...|


#SQL #PostgreSQL #агрегация #count
🔥7
Всем привет!
Давно не было постов, да... Отдыхал, думал, снова учился... В общем то и писать пока что особо не о чём.
Год заканчивался тем, что мой голос совсем пропал, болело горло и я бесконечно чихал =)
Но уже к 3му января, я уже почти вернулся в норму и сейчас чувствую себя хорошо.
Сходил всей семьёй в кино... дважды... на русские фильмы... На Чебурашку 2 (вообще гадость) и Простоквашино (так плохо, что даже хорошо, ахаха). Видели цены??? Я ваще офигел от 450 руб за билет (а их мне надо 4 штуки)... И это на утренние сеансы. А по вечерам цены доходили до 2000 за билет...
А ещё, я не принял оффер, который мне был сделан. Моя чуйка сказала "не надо", а я ей как-то доверяю =) Может и зря, конечно, время покажет.
По учёбе я доделал проект по Apache Airflow: github.com/mishandri/airflow_project
И мне уже дали отличный фидбек на него. Если вкратце, то проект генерирует даг динамически на основе Python-словаря, лежащего в S3-хранилище. Это позволяет достаточно легко изменять работу дага без фактического изменения его кода.
Да, получилось, я считаю, очень интересно. Я постарался применить всё, чему меня научили + ещё кое-что, чего не было рассказано и было изучено самостоятельно.
И приступил к изучению PL/SQL, чтобы уметь писать всякие функции, триггеры, ветвления и циклы.
А у вас было что-то интересное за эти длинные выходные?

@nullpp #SQL #PostgreSQL #Python #Airflow #истории
👍3😁2🤔2
Всем привет!
Как я уже писал ранее, перед самым Новым годом я прошёл собес, и мне был сделан офер. Но я его не принял)
Теперь же, после праздников, я обновил своё резюме и активненько начал снова откликаться на вакансии.
И вот что я вижу - работодатели, мягко говоря, ахерели xD
Вот что должен уметь джун BI-аналитик? Ну ладно, не совсем джун (с небольшим опытом) или даже миддл?
Давайте я сначала напишу что я думаю сам, а потом допишу, что теперь хотят работодатели...

Итак, первое и самое основное:
1. SQL. Это уже, своего рода, обязаловка. SQL сейчас нужен всегда и везде. Что нужно на уверенном уровне:
- SELECT, WHERE, агрегации и GROUP BY, HAVING, ORDER BY, LIMIT
- JOIN'ы всех видов: INNER/LEFT как отче наш, RIGHT/FULL - по настроению =)
- Оконные функции и их применение (SUM, AVG, ROW_NUMBER), причём важно умение настраивать параметры самого окна.
Если этого минимума нет, то дальше и обсуждать нечего!
2. База BI-инструментов. Как быть BI-аналитиком и не знать BI-инструменты?)) Что нужно уметь:
- Подключиться к БД (например, PostgreSQL/Clickhouse)
- Создать датасет/витрину данных со всем нужными полями и вычислениями
- Понимать разницу между мерой и измерением (хотя в разных BI-системах названия могут отличаться, но суть остаётся прежней)
- Понимать какой чарт для каких целей лучше использовать
- Уметь настроить внешний вид чарта (цвета, толщина линий и тд
- Уметь правильно добавить фильтрации/селекторы и тому подобное и уметь настроить их влияние на различные чарты.
3. Немного продуктового мышления. А куда ж без него? Ты должен понимать хотя бы основные метрики того бизнеса, куда хочешь устроиться. Сюда же я отнесу умение получить чёткие ответы на вопросы:
- Для какой цели нужен дашборд?
- Кто будет пользоваться дашбордом?
- Что вы хотите видеть на дашборде (какие метрики, графики и тд)?
- Как это поможет принимать решения?

Это была всё база. Что будет плюсом к этому всему?
- Python. Не знаю как у вас, а меня уже питон выручил несколько раз.
- Git. Тоже очень полезная штука. Важно хотя бы базово понимать как он работает и не бояться его.
- Excel/GoogleSheets. Очень часто заказчик приносит свои данные в обычных табличках, где много всяких дынных и написаны какие-то формулы, которые помогут потом при создании витрины данных или при визуализации.

А теперь я напишу то, что я стал встречать в вакансиях "от 1 до 3 лет" опыта на hh.
- ML. Да, да, работодатель уже хочет, что бы его будущий работник умел "хотя бы" делать линейную регрессию, классификацию или кластеризацию. Про K-means пока не встречал, как и градиентный спуск, но кажется, что ещё полгода и будут требовать и их. Особенно интересуют работодателя проекты с временными рядами. То есть уже надо уметь использовать sklearn или pytorch
- T-SQL. Работодатель хочет, чтобы вы не просто SELECT'или, а создавали свои процедуры, функции и триггеры.
- Умение работать с S3-хранилищами,
- Использование кластеров YandexCloud
- Работа в Linux-окружении
- Понимание Docker/Docker Compose
- Даже видел, что в некоторых вакансиях хотят написание дагов Airflow.

Другими словами, очень много требований, которые вообще не относятся к BI, а больше относятся к DE или ML.
Вот такой вот получился пост (даже немного грустный, как по мне). Требования всё растут и растут, не успеваешь гнаться за ними).

@nullpp #SQL #Python #Airflow #работа #обсуждение
🤔6😢3
Прошёл тест от #avito и #getmach по своим компетенциям, который вот тут https://avito.getmatch.ru/skills-test

Помня, как подтверждаются навыки на hh, что даже нельзя фокус окна переключать, я решил проходить тест полностью своими силами =) По SQL (Clickhouse) как раз вспоминал как извлечь начало месяца для когорты, и написал date_trunc(), потом уже вспомнил про dateTrunc​(). Вроде как теперь обе функции в наличии. Но я всё время путаю, что первым аргументом, а что вторым, видимо тут как раз и перепутал)))

По A/B-тестам согласен с оценкой, здесь у меня только учебный опыт. Теперь я знаю, куда дальше расти и стремиться =)

@nullpp #тест #аналитика #sql
🔥3👍2