HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>В этом уроке мы познакомимся с понятиями баз и витрин данных компании и их различиями. Витрины - важная тема для аналитика данных, так как он работает именно с ними.</p>
1 <p>В этом уроке мы познакомимся с понятиями баз и витрин данных компании и их различиями. Витрины - важная тема для аналитика данных, так как он работает именно с ними.</p>
2 <p>Сегодня мы научимся создавать витрины и работать с ними. Эти навыки помогут построить аналитические отчеты и выявить причины проблем в работе сервисов компании. Например, построить отчет о выручке магазинов сети за период времени и найти самые прибыльные магазины.</p>
2 <p>Сегодня мы научимся создавать витрины и работать с ними. Эти навыки помогут построить аналитические отчеты и выявить причины проблем в работе сервисов компании. Например, построить отчет о выручке магазинов сети за период времени и найти самые прибыльные магазины.</p>
3 <h2>Базы данных систем</h2>
3 <h2>Базы данных систем</h2>
4 <p>Представим, что мы ведем заметки о своей жизни и работе в разных местах. Для учета доходов и расходов мы используем Google-таблицы или специальные приложения. Трекинг рабочих задач производим в Trello. А в Notion записываем мысли о событиях из жизни и ведем дневник. Каждый из этих инструментов удобен для определенных задач.</p>
4 <p>Представим, что мы ведем заметки о своей жизни и работе в разных местах. Для учета доходов и расходов мы используем Google-таблицы или специальные приложения. Трекинг рабочих задач производим в Trello. А в Notion записываем мысли о событиях из жизни и ведем дневник. Каждый из этих инструментов удобен для определенных задач.</p>
5 <p>Это примеры баз данных, которые мы используем в личных целях. У компаний тоже есть разные базы для разных подсистем. Например, у бухгалтерии банка своя база данных, у отдела продаж своя, у отдела кредитного скоринга тоже своя.</p>
5 <p>Это примеры баз данных, которые мы используем в личных целях. У компаний тоже есть разные базы для разных подсистем. Например, у бухгалтерии банка своя база данных, у отдела продаж своя, у отдела кредитного скоринга тоже своя.</p>
6 <p>Обычно базы данных подсистем компании хранятся в нормализованном виде. Покажем, как это выглядит на примере.</p>
6 <p>Обычно базы данных подсистем компании хранятся в нормализованном виде. Покажем, как это выглядит на примере.</p>
7 <p>Допустим, мы отслеживаем ежемесячный поток клиентов в нескольких магазинах сети электроники. Клиенты пользуются именными скидочными картами, и по ним мы отслеживаем каждого по отдельности. Тогда таблица с данными клиентов и купленных ими товарами будет выглядеть так:</p>
7 <p>Допустим, мы отслеживаем ежемесячный поток клиентов в нескольких магазинах сети электроники. Клиенты пользуются именными скидочными картами, и по ним мы отслеживаем каждого по отдельности. Тогда таблица с данными клиентов и купленных ими товарами будет выглядеть так:</p>
8 <p><strong>Purchases</strong></p>
8 <p><strong>Purchases</strong></p>
9 <p>В этой таблице мы видим информацию о транзакциях покупателей в магазине электроники. Здесь есть информация о покупателях, магазинах и товарах.</p>
9 <p>В этой таблице мы видим информацию о транзакциях покупателей в магазине электроники. Здесь есть информация о покупателях, магазинах и товарах.</p>
10 <p>Теперь представим, что один из магазинов переехал на другой адрес. Чтобы внести изменения в эту таблицу, мы выделим все строки, которые содержат старый адрес, и заменим на новый.</p>
10 <p>Теперь представим, что один из магазинов переехал на другой адрес. Чтобы внести изменения в эту таблицу, мы выделим все строки, которые содержат старый адрес, и заменим на новый.</p>
11 <p>Если в таблице тысячи или миллионы строк, тогда придется изменять большое количество. Но это замедляет работу сервиса, и даже может положить его.</p>
11 <p>Если в таблице тысячи или миллионы строк, тогда придется изменять большое количество. Но это замедляет работу сервиса, и даже может положить его.</p>
12 <p>Чтобы не столкнуться с этой проблемой, базы данных таких систем нормализуют - разносят разные объекты по разным таблицам. В таком случае предстоит изменять минимальное количество строк.</p>
12 <p>Чтобы не столкнуться с этой проблемой, базы данных таких систем нормализуют - разносят разные объекты по разным таблицам. В таком случае предстоит изменять минимальное количество строк.</p>
13 <p>Так выглядят нормализованные таблицы:</p>
13 <p>Так выглядят нормализованные таблицы:</p>
14 <p><strong>Shops</strong></p>
14 <p><strong>Shops</strong></p>
15 <p><strong>Customers</strong></p>
15 <p><strong>Customers</strong></p>
16 <p><strong>Products</strong></p>
16 <p><strong>Products</strong></p>
17 <p><strong>Discounts</strong></p>
17 <p><strong>Discounts</strong></p>
18 <p><strong>CustomersDiscounts</strong></p>
18 <p><strong>CustomersDiscounts</strong></p>
19 <p><strong>Purchases</strong></p>
19 <p><strong>Purchases</strong></p>
20 <p>Датасет доступен на DB Fiddle по<a>этой</a>ссылке.</p>
20 <p>Датасет доступен на DB Fiddle по<a>этой</a>ссылке.</p>
21 <p>Здесь представлены следующие таблицы:</p>
21 <p>Здесь представлены следующие таблицы:</p>
22 <ul><li>Shops - информация о магазинах</li>
22 <ul><li>Shops - информация о магазинах</li>
23 <li>Customers - информация о клиентах</li>
23 <li>Customers - информация о клиентах</li>
24 <li>Products - информация о товарах</li>
24 <li>Products - информация о товарах</li>
25 <li>Discounts - информация о скидках</li>
25 <li>Discounts - информация о скидках</li>
26 <li>CustomersDiscounts - таблица, которая связывает клиентов и их персональные скидки</li>
26 <li>CustomersDiscounts - таблица, которая связывает клиентов и их персональные скидки</li>
27 <li>Purchases - таблица покупок</li>
27 <li>Purchases - таблица покупок</li>
28 </ul><p>У каждой из этих таблиц есть поле ID - это уникальный ключ. Также одна таблица содержит в себе информацию только об одной сущности, например: Shops - о магазинах, Customers - о клиентах.</p>
28 </ul><p>У каждой из этих таблиц есть поле ID - это уникальный ключ. Также одна таблица содержит в себе информацию только об одной сущности, например: Shops - о магазинах, Customers - о клиентах.</p>
29 <p>Каждый объект, например, магазин, клиент, представлены одной строкой без дублирования. При этом таблица Purchases может содержать одинаковые ID клиентов, товаров или магазинов, так как клиенты покупают товары в разных магазинах в разное время или одни и те же товары.</p>
29 <p>Каждый объект, например, магазин, клиент, представлены одной строкой без дублирования. При этом таблица Purchases может содержать одинаковые ID клиентов, товаров или магазинов, так как клиенты покупают товары в разных магазинах в разное время или одни и те же товары.</p>
30 <p>Если заменить адрес магазина, мы затронем одну строчку в таблице с магазинами. Остальные таблицы останутся без изменений.</p>
30 <p>Если заменить адрес магазина, мы затронем одну строчку в таблице с магазинами. Остальные таблицы останутся без изменений.</p>
31 <p>CustomersDiscounts - это отдельный вид таблиц. Они содержат в себе только свой ID и ID других таблиц, что позволяет связать эти таблицы. Покупателей и их индивидуальные скидки разносят по разным таблицам.</p>
31 <p>CustomersDiscounts - это отдельный вид таблиц. Они содержат в себе только свой ID и ID других таблиц, что позволяет связать эти таблицы. Покупателей и их индивидуальные скидки разносят по разным таблицам.</p>
32 <p>Например, скидка у отдельного покупателя может увеличиться, когда он за все время купил в магазине много товаров. Мы хотим изменять как можно меньшее количество строк, поэтому меняем значение скидки в CustomersDiscounts, а таблица Customers остается без изменений.</p>
32 <p>Например, скидка у отдельного покупателя может увеличиться, когда он за все время купил в магазине много товаров. Мы хотим изменять как можно меньшее количество строк, поэтому меняем значение скидки в CustomersDiscounts, а таблица Customers остается без изменений.</p>
33 <p>Такие базы данных называются<strong>OLTP</strong>или<strong>Online Transaction Processing</strong>. Online - потому, что базы данных обновляются в реальном времени. Транзакции идут большим потоком, поэтому, чтобы достичь минимального времени отклика, важно вносить изменения в малое количество строк.</p>
33 <p>Такие базы данных называются<strong>OLTP</strong>или<strong>Online Transaction Processing</strong>. Online - потому, что базы данных обновляются в реальном времени. Транзакции идут большим потоком, поэтому, чтобы достичь минимального времени отклика, важно вносить изменения в малое количество строк.</p>
34 <h2>Витрины данных</h2>
34 <h2>Витрины данных</h2>
35 <p>Аналитикам данных сложно работать с большим количеством таблиц, так как каждая из них неинформативная. Аналитики интересуются не ID товаров или магазинов, им нужно знать названия товаров, адреса магазинов, цены с учетом скидки и так далее. Поэтому существуют витрины данных, где собрана вся важная информация.</p>
35 <p>Аналитикам данных сложно работать с большим количеством таблиц, так как каждая из них неинформативная. Аналитики интересуются не ID товаров или магазинов, им нужно знать названия товаров, адреса магазинов, цены с учетом скидки и так далее. Поэтому существуют витрины данных, где собрана вся важная информация.</p>
36 <p>Пример витрины данных - это таблица Purchases. Посмотрим на нее еще раз:</p>
36 <p>Пример витрины данных - это таблица Purchases. Посмотрим на нее еще раз:</p>
37 <p><strong>Purchases</strong></p>
37 <p><strong>Purchases</strong></p>
38 <p>Здесь находится только важная информация: имена клиентов, наименование купленного товара, адрес покупки, и нет ID. Аналитики работают только с витринами, потому что они удобны для анализа и построения отчетов.</p>
38 <p>Здесь находится только важная информация: имена клиентов, наименование купленного товара, адрес покупки, и нет ID. Аналитики работают только с витринами, потому что они удобны для анализа и построения отчетов.</p>
39 <p>Напомним, что обычно в компаниях базы данных для каждого отдела разные. Аналитики обычно не анализируют все данные сразу, поэтому витрины - это срез во всех данных компании. Их еще называют<strong>Data Mart</strong>.</p>
39 <p>Напомним, что обычно в компаниях базы данных для каждого отдела разные. Аналитики обычно не анализируют все данные сразу, поэтому витрины - это срез во всех данных компании. Их еще называют<strong>Data Mart</strong>.</p>
40 <p>Представим общую схему потока данных между базами разных отделов и витринами:</p>
40 <p>Представим общую схему потока данных между базами разных отделов и витринами:</p>
41 <p>Здесь видно, что каждый отдел компании содержит свою базу данных, а таблицы в базах хранятся в нормализованном виде. Витрины данных - это срезы в хранилище данных для разных аналитических задач. Одна витрина представляется не более чем одной базой.</p>
41 <p>Здесь видно, что каждый отдел компании содержит свою базу данных, а таблицы в базах хранятся в нормализованном виде. Витрины данных - это срезы в хранилище данных для разных аналитических задач. Одна витрина представляется не более чем одной базой.</p>
42 <p>Витрины данных могут быть базами данных или таблицами в Google Sheets, это не меняет их сути.</p>
42 <p>Витрины данных могут быть базами данных или таблицами в Google Sheets, это не меняет их сути.</p>
43 <p>Теперь разберемся, как работать с витриной. Для этого создадим ее.</p>
43 <p>Теперь разберемся, как работать с витриной. Для этого создадим ее.</p>
44 <h2>Создаем витрину</h2>
44 <h2>Создаем витрину</h2>
45 <p>Откроем базу данных Purchases. Мы увидим в ней таблицы, которые были в примерах урока:</p>
45 <p>Откроем базу данных Purchases. Мы увидим в ней таблицы, которые были в примерах урока:</p>
46 <ul><li>Customers</li>
46 <ul><li>Customers</li>
47 <li>CustomersDiscounts</li>
47 <li>CustomersDiscounts</li>
48 <li>Discounts</li>
48 <li>Discounts</li>
49 <li>Products</li>
49 <li>Products</li>
50 <li>Purchases</li>
50 <li>Purchases</li>
51 <li>Shops</li>
51 <li>Shops</li>
52 </ul><p>Посмотрим на таблицу Purchases:</p>
52 </ul><p>Посмотрим на таблицу Purchases:</p>
53 <p><strong>purchases.purchases</strong></p>
53 <p><strong>purchases.purchases</strong></p>
54 <p>В этой таблице 13 строк, каждая строка - отдельная покупка. Нам нужно получить таблицу, где вся информация представлена понятным образом, а не через id. Выпишем все поля, которые хотим получить в витрине:</p>
54 <p>В этой таблице 13 строк, каждая строка - отдельная покупка. Нам нужно получить таблицу, где вся информация представлена понятным образом, а не через id. Выпишем все поля, которые хотим получить в витрине:</p>
55 <ul><li>date - дата покупки</li>
55 <ul><li>date - дата покупки</li>
56 <li>full_name - ФИО покупателя</li>
56 <li>full_name - ФИО покупателя</li>
57 <li>shop_address - адрес магазина</li>
57 <li>shop_address - адрес магазина</li>
58 <li>product_name - наименование товара</li>
58 <li>product_name - наименование товара</li>
59 <li>price - исходная цена товара в рублях</li>
59 <li>price - исходная цена товара в рублях</li>
60 <li>discount - скидка в долях от единицы</li>
60 <li>discount - скидка в долях от единицы</li>
61 <li>discounted_price - цена товара после индивидуальной скидки покупателю</li>
61 <li>discounted_price - цена товара после индивидуальной скидки покупателю</li>
62 </ul><p>Таблица Purchases будет основной связующей с другими таблицами. Друг с другом связаны только таблицы customers и discounts через промежуточную таблицу customersdiscounts.</p>
62 </ul><p>Таблица Purchases будет основной связующей с другими таблицами. Друг с другом связаны только таблицы customers и discounts через промежуточную таблицу customersdiscounts.</p>
63 <p>Чтобы создать витрину, нужно объединить нормализованные таблицы джойнами. В нашем случае в таблицах нет NULL-значений, поэтому мы можем использовать любой вид джойнов, например, INNER JOIN. INNER JOIN - это разновидность джойна, которая связывает таблицы по ненулевым ключам. Если ключ какой-то строки имеет значение NULL, эта строка не попадает в итоговую таблицу.</p>
63 <p>Чтобы создать витрину, нужно объединить нормализованные таблицы джойнами. В нашем случае в таблицах нет NULL-значений, поэтому мы можем использовать любой вид джойнов, например, INNER JOIN. INNER JOIN - это разновидность джойна, которая связывает таблицы по ненулевым ключам. Если ключ какой-то строки имеет значение NULL, эта строка не попадает в итоговую таблицу.</p>
64 <p>Если в ключах есть NULL-значения, а мы все равно хотим включить эти строки в итоговую таблицу, мы воспользуемся LEFT JOIN, RIGHT JOIN или FULL OUTER JOIN. В таком случае мы выберем джойн исходя из того, включать ли нулевые ключи только левой таблицы, правой или обеих.</p>
64 <p>Если в ключах есть NULL-значения, а мы все равно хотим включить эти строки в итоговую таблицу, мы воспользуемся LEFT JOIN, RIGHT JOIN или FULL OUTER JOIN. В таком случае мы выберем джойн исходя из того, включать ли нулевые ключи только левой таблицы, правой или обеих.</p>
65 <p>Теперь нужно понять, откуда взять нужные нам поля. Например, date - это дата покупки, поэтому возьмем ее из таблицы Purchases. А full_name есть в таблице customers. Попробуем составить селект, чтобы получить два этих поля:</p>
65 <p>Теперь нужно понять, откуда взять нужные нам поля. Например, date - это дата покупки, поэтому возьмем ее из таблицы Purchases. А full_name есть в таблице customers. Попробуем составить селект, чтобы получить два этих поля:</p>
66 <p>В customers id покупателя называется id, так как эта таблица про покупателей, и id покупателя в ней - это уникальный ключ. А таблица Purchases о покупках. Покупатели в ней могут повторяться, поэтому поле называется customer_id.</p>
66 <p>В customers id покупателя называется id, так как эта таблица про покупателей, и id покупателя в ней - это уникальный ключ. А таблица Purchases о покупках. Покупатели в ней могут повторяться, поэтому поле называется customer_id.</p>
67 <p>shop_address - это адрес магазина, то есть поле address в таблице Shops. Добавим джойн с этой таблицей:</p>
67 <p>shop_address - это адрес магазина, то есть поле address в таблице Shops. Добавим джойн с этой таблицей:</p>
68 <p>product_name и price мы возьмем из таблицы Products:</p>
68 <p>product_name и price мы возьмем из таблицы Products:</p>
69 <p>Остались поля discount и discounted_price. Мы помним, что таблицы Discount и Customers связаны через CustomersDiscounts. Поэтому мы объединим скидки с покупателями через дополнительную таблицу. В итоге посчитаем discounted_price по следующей формуле:</p>
69 <p>Остались поля discount и discounted_price. Мы помним, что таблицы Discount и Customers связаны через CustomersDiscounts. Поэтому мы объединим скидки с покупателями через дополнительную таблицу. В итоге посчитаем discounted_price по следующей формуле:</p>
70 <p>Итоговый запрос будет выглядеть так:</p>
70 <p>Итоговый запрос будет выглядеть так:</p>
71 <p><strong>data_mart</strong></p>
71 <p><strong>data_mart</strong></p>
72 <p><a>Ссылка на таблицы</a></p>
72 <p><a>Ссылка на таблицы</a></p>
73 <h2>Работаем с витриной</h2>
73 <h2>Работаем с витриной</h2>
74 <p>Допустим, нам нужно посчитать суммарную выручку по каждому из магазинов. Для этого используем агрегирующую функцию SUM с группировкой по магазинам. Функция SUM позволяет посчитать сумму всех значений покупок в каждой из групп. Группы формируются с помощью GROUP BY, и наши группы - это каждый отдельный магазин.</p>
74 <p>Допустим, нам нужно посчитать суммарную выручку по каждому из магазинов. Для этого используем агрегирующую функцию SUM с группировкой по магазинам. Функция SUM позволяет посчитать сумму всех значений покупок в каждой из групп. Группы формируются с помощью GROUP BY, и наши группы - это каждый отдельный магазин.</p>
75 <p>Для начала создадим новую таблицу purchasesDataMart и запишем в нее нашу витрину. Мы создаем новую таблицу, чтобы в дальнейшем можно было обращаться только к ней с другими запросами.</p>
75 <p>Для начала создадим новую таблицу purchasesDataMart и запишем в нее нашу витрину. Мы создаем новую таблицу, чтобы в дальнейшем можно было обращаться только к ней с другими запросами.</p>
76 <p>В запросе выше мы объединили все таблицы в одну и записали нашу витрину в новую таблицу.</p>
76 <p>В запросе выше мы объединили все таблицы в одну и записали нашу витрину в новую таблицу.</p>
77 <p>Теперь мы можем составить запрос к таблице витрины:</p>
77 <p>Теперь мы можем составить запрос к таблице витрины:</p>
78 <p>Итоговая таблица выглядит так:</p>
78 <p>Итоговая таблица выглядит так:</p>
79 <p><strong>purchases.purchasesDataMart</strong></p>
79 <p><strong>purchases.purchasesDataMart</strong></p>
80 <p><a>Ссылка на таблицу</a></p>
80 <p><a>Ссылка на таблицу</a></p>
81 <p>В этой таблице мы видим суммарную выручку по каждому из магазинов в колонке total_earnings.</p>
81 <p>В этой таблице мы видим суммарную выручку по каждому из магазинов в колонке total_earnings.</p>
82 <p>Мы создали витрину данных и записали ее в таблицу purchasesDataMart, а также создали свой первый отчет по витрине.</p>
82 <p>Мы создали витрину данных и записали ее в таблицу purchasesDataMart, а также создали свой первый отчет по витрине.</p>
83 <h2>Выводы</h2>
83 <h2>Выводы</h2>
84 <p>В этом уроке мы рассмотрели концепцию OLTP и витрин данных. Витрины данных - это срезы во всех данных компании, которые интересны аналитику данных. Витрины содержат в себе более информативные таблицы, чем базы OLTP, которые нормализованы и связаны друг с другом с помощью ключей id.</p>
84 <p>В этом уроке мы рассмотрели концепцию OLTP и витрин данных. Витрины данных - это срезы во всех данных компании, которые интересны аналитику данных. Витрины содержат в себе более информативные таблицы, чем базы OLTP, которые нормализованы и связаны друг с другом с помощью ключей id.</p>
85 <p>Мы научились создавать витрину. Чтобы превратить таблицы в базе в витрину, нужно объединить информативные поля из разных таблиц по ключам. Главный ключ в каждой из таблиц - это уникальное поле. Обычно он называется id.</p>
85 <p>Мы научились создавать витрину. Чтобы превратить таблицы в базе в витрину, нужно объединить информативные поля из разных таблиц по ключам. Главный ключ в каждой из таблиц - это уникальное поле. Обычно он называется id.</p>
86 <p>Когда у нас уже есть витрина, мы можем строить по ней отчеты и выявлять закономерности.</p>
86 <p>Когда у нас уже есть витрина, мы можем строить по ней отчеты и выявлять закономерности.</p>
87 <p>Витрины данных очень важны в аналитике данных, и вы будете с ними постоянно сталкиваться в дальнейшем.</p>
87 <p>Витрины данных очень важны в аналитике данных, и вы будете с ними постоянно сталкиваться в дальнейшем.</p>