docs(labs): расследования выручки привязаны к задачам DE

Зачем: результатом лабораторных должны быть обоснованные решения о подготовке данных для витрин.

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

Проверка: SELECT-запросы под analyst, расчеты по сохраненной истории девяти наблюдений, 54 локальные ссылки, git diff --check и независимое техническое ревью.
This commit is contained in:
ddadmin committed 2026-09-22 04:28:27 -04:00
1 parent bb087f4477
commit 3e9249933b
6 files changed
+119 -57

No files matched your search

+5 -5
View File
@@ -124,16 +124,16 @@ DM](../architecture/dm.md).
### Почему выручка не сходится
Открывается после ступени 1. Четыре расследования:
Открывается после ступени 1. Четыре расследования качества данных:
- [Куда пропали покупки](optional/missing-purchases.md): найти заказы без
события в трекере и объяснить разрыв воронки.
события, выбрать источник витрины и условие проверки полноты.
- [Почему повтор покупки завышает выручку](optional/duplicate-purchases.md):
посчитать деньги по номеру заказа и объяснить вклад повторов.
выбрать зерно и ключ расчета, проверить его на повторных событиях.
- [Какая позиция объясняет разницу в сумме](optional/order-amount-difference.md):
сопоставить корзины и найти причину расхождения до копейки.
разобрать позиции без потери точности и локализовать расхождение источников.
- [Почему вчерашняя выручка меняется сегодня](optional/revenue-over-time.md):
проследить опоздания и отмены, затем определить момент закрытия дня.
обосновать окно пересчета витрины и требования к истории заказов.
Первые три работы используют готовые данные. Четвертая продвигает мир через
Airflow; для нее вы сохраняете состояния заказов после каждого модельного дня.
+25 -12
View File
@@ -1,14 +1,17 @@
# Почему повтор покупки завышает выручку
**Чему учит:** отличать повторную доставку строки от повторного события об
одной покупке и выбирать ключ, по которому считать деньги.
**Чему учит:** выбрать зерно и ключ расчета, чтобы повторные события
не умножали денежную сумму.
Факультатив доступен после ступени 1. Работайте в DBeaver пользователем
`analyst` по [инструкции](../../../README.md#подключиться-из-dbeaver).
Дождитесь завершения `etl_pipeline`; оставьте `world_live` на паузе и
дождитесь уже начатых прогонов, чтобы данные не менялись между запросами.
## Посчитайте клиентскую сумму двумя способами
## Проверьте расчет по событиям
В ODS уже устранены повторные доставки событий. Достаточно ли этого,
чтобы сложить суммы всех `purchase` для витрины заказов? Проверьте на данных.
Возьмите один закрытый день: его дата должна быть не позднее
`max(snapshot_date) - 6` из `ods.order_v`. Во всех запросах к `dds.event_v`
@@ -24,10 +27,16 @@
Для двух повторившихся покупок выпишите `event_id`, `client_id`, `event_time`,
номер заказа и сумму. Сопоставьте число событий и заказов в `dds.order_v`.
Теперь рассчитайте клиентскую сумму, учитывая каждый номер заказа один раз.
До выбора одной суммы на заказ проверьте, что во всех его событиях она
одинакова. Проверьте свое решение на случае двух разных заказов с одинаковой
суммой: сколько денег оно учтет?
## Соберите расчет по заказам
Напишите запрос с одной строкой на номер заказа. Сохраните в результате
номер, число исходных событий и одну заявленную сумму. До выбора суммы
проверьте, что во всех событиях заказа она одинакова. Затем посчитайте итог
дня по результату этого запроса и сравните с расчетом по событиям.
Проверьте, что номера в результате уникальны, а число строк совпадает с числом
разных номеров в исходных событиях. Отдельно проверьте свое решение на случае
двух разных заказов с одинаковой суммой: сколько денег оно учтет?
## Найдите заказы, из-за которых сумма завышена
@@ -49,7 +58,7 @@
его статус и [порядок присвоения классов](../../architecture/dm.md#dmpurchase_vs_orders_v).
Класс витрины не заменяет поиск всех повторов в событиях.
## Сравните с выручкой магазина
## Определите границы расчета
Сложите `revenue` из `dm.revenue_daily_v` за тот же `report_date` по всем
категориям. Эта витрина считает стоимость позиций оплаченных заказов,
@@ -60,10 +69,14 @@
заказ, который объясняет, почему деньги трекера и магазина все еще могут
различаться. Для этого сопоставьте события, заказ и готовую сверку.
Рядом со своим запросом укажите его зерно и ключ. Обоснуйте, где нужна одна
строка на событие, а где — одна на заказ: следует ли ради этого расчета
удалять повторные покупки из `dds.event_v`? Используйте найденные `event_id`.
## Что должно получиться
- [ ] сохранены две клиентские суммы и строки повторившихся покупок;
- [ ] сохранен запрос с одной строкой на заказ, числом событий и суммой;
- [ ] уникальность ключа и полнота набора номеров проверены по источнику;
- [ ] разность сумм полностью объяснена вкладом лишних событий;
- [ ] выбор ключа для устранения повторов подтвержден данными;
- [ ] вы можете объяснить, почему устранение повторов не завершает сверку
выручки с магазином.
- [ ] обоснованы ключ расчета и место устранения повторов;
- [ ] найден случай, показывающий границы расчета денег по трекеру.
+22 -12
View File
@@ -1,7 +1,7 @@
# Куда пропали покупки
**Чему учит:** обнаружить потерю событий при сверке двух источников и
обосновать, каким данным можно доверять при подсчете покупок.
**Чему учит:** проверить полноту данных по независимому источнику и выбрать
источник для витрины заказов.
Факультатив доступен после ступени 1. В DBeaver подключитесь пользователем
`analyst` по [инструкции](../../../README.md#подключиться-из-dbeaver).
@@ -10,8 +10,9 @@
## Выберите день
Магазин зарегистрировал заказы, но часть событий покупки не дошла до трекера.
Найдите след этой потери сначала в событиях сайта, затем в заказах.
Можно ли построить полную витрину заказов по событиям `purchase`?
Проверьте это на одном дне: сначала сопоставьте события сайта, затем сверьте
номера заказов с выгрузкой магазина.
Возьмите день, для которого уже получен последний слепок семидневного окна.
Запрос показывает самую позднюю подходящую дату:
@@ -46,6 +47,9 @@ FROM ods.order_v;
В событии номер заказа находится в `purchase_id[1]`, в заказах — в `order_id`.
Соберите список заказов выбранного дня, для которых нет события покупки.
Несколько событий с одним номером заказа должны оставаться одной покупкой.
Сохраните запрос сверки: на каждый такой заказ он должен возвращать дату,
номер и статус. Дату задавайте в одном месте, чтобы запрос можно было
повторить для другого дня.
Проверьте два равенства:
@@ -67,9 +71,6 @@ FROM ods.order_v;
к устройству этого стенда; для другого источника его нужно проверять заново.
Если в выбранном дне повторов нет, возьмите другой закрытый день.
Для оценки доли потерь используйте число заказов магазина. Затем посчитайте
долю с тем же числителем, но с числом просмотров подтверждения в знаменателе.
Совпали ли результаты? Свяжите различие знаменателей с найденными событиями.
## Сопоставьте вывод с готовой сверкой
@@ -80,13 +81,22 @@ FROM ods.order_v;
объясните, почему потеря события не всегда попадает в `lost_event`.
Возьмите один заказ из своего списка и сохраните два запроса: первый находит
его в магазине, второй показывает отсутствие покупки в трекере. Сформулируйте,
какой источник нужен для отчета о поведении посетителей, а какой — для денег.
его в магазине, второй показывает отсутствие покупки в трекере.
## Выберите источник и условие проверки
По результатам сверки укажите источник для витрины, в которой должен быть
каждый зарегистрированный заказ. Обоснуйте выбор найденными номерами.
Рядом с запросом запишите, когда его результат можно считать окончательным.
Что изменится, если запустить его до получения всех слепков выбранного дня?
Позволяет ли отсутствие события в `dds.event_v` установить место потери —
до приема в хранилище или при обработке? Какие данные нужны, чтобы это выяснить?
## Что должно получиться
- [ ] сохранены день, счетчики воронки и список заказов без события;
- [ ] сохранен запрос сверки по дате, возвращающий заказы без события;
- [ ] оба равенства сходятся, влияние повторного просмотра объяснено;
- [ ] доля потерь посчитана с обоснованным знаменателем;
- [ ] один случай подтвержден запросами к обоим источникам;
- [ ] вы различаете отсутствие события и класс строки в готовой сверке.
- [ ] источник витрины выбран по результатам сверки;
- [ ] указаны условие окончательной проверки и границы ее выводов.
+20 -7
View File
@@ -1,7 +1,7 @@
# Какая позиция объясняет разницу в сумме
**Чему учит:** перейти от расхождения суммы заказа к конкретному товару и
проверить объяснение с точностью до копейки.
**Чему учит:** разобрать вложенные данные без потери точности и локализовать
расхождение двух источников до товарной позиции.
Факультатив доступен после ступени 1. В DBeaver используйте пользователя
`analyst` из [инструкции подключения](../../../README.md#подключиться-из-dbeaver).
@@ -10,6 +10,9 @@
## Найдите заказ
Суммы покупки в трекере и заказа в магазине различаются. Разберите их позиции
и проверьте отдельно точность своего запроса и различия между событием и заказом.
В `dm.purchase_vs_orders_v` выберите один заказ с
`mismatch_class = 'amount_delta'`. Возьмите закрытый день: `order_day`
не позднее `max(snapshot_date) - 6` из `ods.order_v`. Сохраните `order_id`,
@@ -40,7 +43,9 @@
Сопоставьте позиции по артикулу так, чтобы остались видны товары,
присутствующие только с одной стороны. Для каждой позиции сравните наличие,
цену и количество. Что различается и сколько это добавляет к расхождению
сумм? В результате нужны строки товаров, а не только две итоговые суммы.
сумм?
Сохраните запрос сверки для выбранных даты и номера заказа; в результате
оставьте артикул, значения с обеих сторон и разность стоимостей позиций.
## Проверьте объяснение
@@ -58,14 +63,22 @@
[форматом выгрузки](../../formats/clickstream-event.md). Если все цены
выбранной корзины целые, возьмите еще один заказ с расхождением и дробной ценой.
В коротком объяснении назовите заказ, товар, количество, цену и разницу.
Какие строки подтверждают найденное расхождение? Есть ли в источниках
сведения о том, почему оно возникло? Отделите наблюдения от предположений.
## Выберите поля для точного расчета
Укажите рядом с запросом, откуда брать цену, каким типом ее читать и по какому
ключу сопоставлять позиции. Подтвердите выбор результатами обеих сверок:
суммы разобранных позиций с суммой своего источника и позиций двух источников
между собой. Какой результат укажет на ошибку вашего разбора, а какой
потребует искать причину выше — в данных, которые получил запрос?
## Что должно получиться
- [ ] позиции клиента и магазина сопоставлены по артикулам;
- [ ] сохранен запрос сверки позиций, не теряющий товары без пары;
- [ ] все три равенства сходятся до копейки;
- [ ] найден пример потери точности в готовом массиве цен;
- [ ] расхождение объяснено конкретной позицией, а скидка и доставка
отделены от сравнения корзин.
- [ ] выбор полей, типа денег и ключа сопоставления подтвержден расчетами;
- [ ] расхождение источников сверки отделено от ошибки своего разбора и различия
между стоимостью корзины и итогом со скидкой и доставкой.
+29 -16
View File
@@ -1,13 +1,13 @@
# Почему вчерашняя выручка меняется сегодня
**Чему учит:** объяснять изменения уже рассчитанного отчета поступлением
заказов и сменой их статусов, определять момент закрытия дня и границы
доступной истории.
**Чему учит:** обосновать окно пересчета витрины и требования к истории
заказов по наблюдаемым опозданиям и изменениям статусов.
Факультатив доступен после ступени 1. Понадобятся Airflow и DBeaver с
подключением `analyst` по [инструкции](../../../README.md#подключиться-из-dbeaver).
Вы будете наблюдать один день оформления заказов, продвигая мир по одному
модельному дню. Новые данные останутся в стенде.
модельному дню. Проверьте, можно ли при загрузке выручки каждый раз считать
только новый день. Новые данные останутся в стенде.
## Подготовьте первое наблюдение
@@ -73,7 +73,7 @@ SELECT
в конце окна и за его пределами.
От исходного наблюдения потребуется восемь однодневных запусков.
## Объясните изменения отчета
## Найдите изменения в уже загруженном дне
После каждого шага сравнивайте заказы по `order_id`, а не по положению строк
в выгрузке. Найдите:
@@ -93,11 +93,12 @@ SELECT
выше; учтите и заказы, которых еще не было в первом наблюдении. Сумма
изменений вкладов должна совпасть с изменением `revenue` до копейки.
Для одного из этих отмененных заказов сравните изменение его вклада
с изменением общей выручки между теми же наблюдениями. Совпало ли
направление изменений? Найдите в своей таблице заказы, определившие общий итог.
Покажите на этих наблюдениях, какой результат остался бы в витрине,
если бы конвейер после первого расчета обрабатывал только новые дни заказов.
Достаточно ли добавлять в старый день только опоздавшие заказы? Проверьте
свой ответ на найденных изменениях статусов.
## Что известно об отменах
## Определите, какую историю нужно хранить
Возьмите отмененный заказ, у которого в вашей истории был статус `paid`.
Укажите два наблюдения, доказывающих, что он был оплачен, а затем отменен.
@@ -105,9 +106,14 @@ SELECT
Теперь возьмите отмененный заказ, для которого ни в одной вашей выгрузке
нет `paid`. Проверьте утверждение «этот заказ никогда не был оплачен»:
что известно о его состоянии между двумя слепками? Достаточно ли сохраненных
наблюдений для такого вывода? Укажите, какие данные позволили бы его проверить.
наблюдений для такого вывода?
## Когда день закрыт
Сформулируйте требования к данным для двух задач: восстановить состояние
витрины на момент прошлого расчета и узнать, был ли заказ когда-либо оплачен.
Какие сведения для каждой задачи должен передавать источник и сохранять
хранилище? Проверьте предложение на своих выгрузках и на промежутке между ними.
## Задайте правило пересчета
Сравните сохраненные состояния при S = D + 6 и S = D + 7: состав заказов,
их статусы, суммы и выручку. Какой слепок последним мог изменить заказы дня D
@@ -115,6 +121,12 @@ SELECT
можно считать окончательным. Было бы достаточно совпадения двух соседних
сумм, если бы окно еще не закончилось?
Запишите правило выбора дней для пересчета после очередного слепка.
Считайте, что начальная история уже загружена и ежедневные прогоны не
пропускались. Укажите, по какой дате определяются границы, какие дни нужно
пересчитать и когда день можно перестать включать в расчет. Подтвердите
правило своими наблюдениями, включая опоздание и отмену.
После собственных выводов сверьтесь с описанием
[слепка и его доставки](../../architecture/orders/snapshot.md#слепок-и-его-доставка)
и [границ истории отмен](../../architecture/orders/fate.md#судьба-заказа).
@@ -122,12 +134,13 @@ SELECT
## Что должно получиться
- [ ] сохранена последовательность наблюдений одного дня D с датами слепков S;
- [ ] найдены опоздавшие заказы и изменения статусов;
- [ ] изменение выручки между двумя наблюдениями объяснено вкладами заказов;
- [ ] на опоздавших заказах и изменениях статусов показаны ошибки загрузки
только новых дней или только новых заказов;
- [ ] изменение выручки между наблюдениями сходится с изменением вкладов заказов;
- [ ] оплата одной из последующих отмен подтверждена двумя наблюдениями;
- [ ] вы различаете доказанную оплату и отсутствие сведений о ней;
- [ ] состояние дня за пределами окна совпало с окончательным, а момент
закрытия обоснован правилом доставки слепков.
- [ ] сформулированы требования к истории расчетов и истории оплаты;
- [ ] правило пересчета и момент закрытия дня обоснованы наблюдениями
и правилом доставки слепков.
После работы оставьте `world_live` на паузе либо верните автоматическое
продвижение, если пользовались им до наблюдения.