Оформление
Связи между таблицами
Когда таблицу добавляют на холст, связи по внешним ключам источника появляются сами: если в базе объявлено, что orders.customer_id ссылается на customers.customer_id, линия между таблицами уже будет. Остальные связи задаются вручную: перетащите мышью кружок рядом с полем одной таблицы на поле другой. На линии связи платформа покажет её тип — например, 1 : M.
Связи нужны, чтобы платформа знала, как соединять данные при построении виджета: например, подставить название товара из справочника к строке заказа.
Щёлкните по линии связи — в правой панели откроются её параметры:
- Условие — какие поля сравниваются и каким оператором (
=,≠,<,>,≤,≥). - Способ связи —
RelationилиJOIN. - Кардинальность —
1 : 1,1 : MилиM : 1(только дляRelation). - Тип соединения —
INNER JOIN,LEFT JOIN,RIGHT JOINилиFULL OUTER(только дляJOIN).

Relation или JOIN
Разница не в том, какой SQL получится, а в том, проверяет ли платформа корректность агрегации.
Relation | JOIN | |
|---|---|---|
| Кардинальность | задаётся и учитывается | не задаётся |
| Проверка на задвоение сумм | есть | нет |
| Когда виджет не построится | если связь размножает строки | никогда, ответственность на вас |
| Тип соединения | выбирает платформа по кардинальности | задаётся: INNER, LEFT, RIGHT, FULL OUTER |
Relation — выбор по умолчанию: платформа знает, сколько строк соответствует строке, и не даст построить виджет, в котором суммы задвоятся. JOIN выполняет соединение как есть: проверки отключены целиком.
JOIN не защищает от задвоения сумм
Со связью Relation и кардинальностью 1 : M платформа отказывается строить виджет, а с тем же 1 : M, переключённым на JOIN, строит его без предупреждений. Совпали ли при этом цифры — зависит только от данных: если справочник действительно содержит дубли по ключу, выручка вырастет на пустом месте, и никакого предупреждения не будет.
Выбирайте JOIN, только если сами контролируете уровень детализации, — например, соединяете две таблицы фактов и знаете, что дублей по ключу в них нет.
Какую кардинальность выбрать
Кардинальность описывает, сколько строк одной таблицы соответствует строке другой, — а не то, как выглядят поля в условии. Для связи таблицы фактов со справочником (заказы → товары) правильное значение — M : 1: у одного товара много заказов, а у каждого заказа ровно один товар.
Платформа проставляет обратное значение
При перетаскивании от таблицы фактов к справочнику подставляется 1 : M. С такой настройкой виджет не построится:
Поля [products] нельзя показать вместе с мерами этого виджета: связь [orders] → [products] размножает строки — одной строке [orders] соответствует несколько строк [products], поэтому меры посчитались бы с задвоением. Проверьте кардинальность связи [orders] → [products] в схеме датасета: сейчас она говорит, что на стороне [products] несколько строк. Если строка там одна — поменяйте кардинальность. Другой вариант — убрать поля [products] из виджета.
Сообщение называет обе таблицы и предлагает два выхода: сменить кардинальность на M : 1 или убрать из виджета поля размножающей таблицы.
С 1 : 1 платформа виджет не блокирует — она считает, что строке соответствует ровно одна строка. Но не выбирайте её только ради того, чтобы виджет построился: если в справочнике окажутся дубли, суммы задвоятся, а предупреждения уже не будет.
Многие ко многим
Вариант M : M в интерфейсе не предлагается: одной связью такое отношение не выражается. Попытка задать его через API заканчивается отказом:
Связь many_to_many между [orders] и [products] на одном ребре не поддерживается; смоделируйте мост (две связи)
Мост — это промежуточная таблица, где каждая строка соединяет одну запись слева с одной справа. К ней ведут две обычные связи M : 1, и обе стороны остаются однозначными.
Сколько размножающих связей допускается
Группа мер — это набор таблиц, из которых виджет берёт меры, вместе со связями между ними: одна ветка дерева соединений. Если все меры виджета считаются по заказам, группа одна; если часть мер приходит из другой таблицы фактов, групп становится две, и платформа собирает их отдельно.
В одной группе мер допускается не более одной связи, размножающей строки. И только если её таблица служит мостом: нужна лишь для перехода и сама не участвует ни в измерениях, ни в мерах. Две такие связи и больше дадут отказ:
Обнаружено несколько связей-размножений (2) в одной группе мер (chasm trap); агрегация мер неоднозначна
Так возникает известная ошибка: две таблицы фактов, связанные с одним справочником, при соединении перемножают строки друг друга. Разносите такие меры по разным виджетам или сводите их заранее в SQL-блоке.
Таблицы из разных источников
Датасет собирается поверх нескольких источников, и они могут быть разных типов: таблица из PostgreSQL и таблица из ClickHouse связываются в одном датасете так же, как две таблицы одной базы. Платформа собирает такой запрос сама — в журнале обращений он помечен как федеративный.
Порядок обычный: подключите оба источника к датасету, добавьте таблицы на холст и свяжите их по общему полю.
Без связи второй источник в запрос не попадёт
Если связи нет, виджет отвечает «Нет связи между [таблица] и [таблица]», а в режиме прямого запроса поле второй таблицы вообще не находится: в план запроса попадает только главный объект. Это не особенность разных СУБД — так же ведёт себя пара таблиц одной базы.
Такой датасет работает: таблица PostgreSQL и таблица ClickHouse, связь по общему ключу, виджет с измерением из первой базы и мерой из второй — выборка строится и возвращает данные.
Что стоит помнить при таком датасете:
- в режиме прямого запроса платформа читает обе базы и соединяет результаты у себя, поэтому объём и скорость зависят от обеих сторон;
- в режиме извлечения обе таблицы выгружаются в витрину, и соединение выполняется уже внутри неё — материализация;
- правила кардинальности те же: связь, размножающая строки, размножит их и здесь.
Что дальше
Связи определяют, как соберётся запрос. Что именно попадёт в виджеты — решает материализация и настройка полей.