Как стать автором
Обновить

Комментарии 30

Вроде бы в предыдущей статье в комментариях разобрались, что диаграммы Венна все ясно и доступно иллюстрируют. Только показывают они не пересечение или объединение строк таблиц, а пересечение или объединение ключей. Я на всякий случаю дублирую этим комментарием эту мысль.
Я не понимаю, зачем при объяснении джойнов завязываться на какие-то там ключи.
В подавляющем большинстве случаев JOIN связывают отношения по первичным и внешним ключам. Хотя технически можно связывать по произвольному выражению. И по скорости тоже — были бы индексы. Поэтому я склоняюсь к тому чтобы в JOIN-ах использовать только первичные и внешние ключи а в условиях WHERE — условия фильтрации. Вот почему для объяснения джойнов завязываться на первичные и внешние ключи не только обсуждаемо но и необходимо.
я склоняюсь к тому чтобы

Предлагаете изменить стандарт или просто не учить людей стандарту, что бы они на сложных вещах ошибались? Если стандарту всё же учить, диаграммы Венна не подходят.


Как диаграммы Венна покажут пересечение ключей при расчёте накопительного итога?

В чем я предлагаю нарушить стандарт? Это все в рамках стандарта. В стандарте в качестве условий WHERE и JOIN выступает одна и та же спецификация *search condition* что фактически означает что можно задавать условия соединения двух таблиц в WHERE а условия фильтрации в JOIN. Но почему бы не сделать семантическое разделение и в условии JOIN задавать условия соединения таблиц а в условиях WHERE — условия фильтрации полученных соединений.

Что касается накопительный итог — не совсем понимаю что имеется в виду. Если можно поясните пожалуйста на примере?
Что касается накопительный итог — не совсем понимаю что имеется в виду. Если можно поясните пожалуйста на примере?


Это, например, когда у вас
FROM A JOIN B ON B.date <= A.date
В этом выражении (в общем случае) нет ни первичных ни внешних ключей. Следовательно не будет и их объединений и пересечений. И я бы записал этот факт в равнозначном выражении FROM A, B WHERE B.date <= A.date

Мне кажется что сразу становится понятным что берется просто декартово произведение таблиц и фильтруется по значению.

Случай с JOIN конечно не покроет того случая когда нужно взять левый или проавый JOIN: FROM A LEFT JOIN B ON B.date <= A.date Но это уже как бы гангстерский метод получения итогов. Я скорее применил что-то вроде этого запроса

SELECT ID, (SELECT SUM(amount) FROM B WHERE B.date <= A.date) as total_amouint FROM A
В таких случаях, обычно, не фильтруется, а агрегируется (например считается тот самый «нарастающий итог»).

И да, автор статьи немного смешал понятия (то есть статья, в большей степени, академическая, чем промышленная). Обычно в качественно спроектированных БД, которые эксплуатируются в реальной жизни соединения (JOIN) происходят по ключам (первичные-внешние), в ключах не бывает NULL'ов и так далее. Но так бывает не всегда. О чём, собственно, и статья.
почему бы не сделать семантическое разделение

Вы не предлагаете его нарушить, вы видимо предлагаете его поменять.


Про накопительный итог вам ниже рассказали. Каким образом диаграммы Венна покажут пересечение ключей при расчёте накопительного итога?


можно задавать условия соединения двух таблиц в WHERE а условия фильтрации в JOIN

Нельзя. LEFT JOIN не взаимозаменяем с WHERE, если есть null.

Про накопительный итог вам ниже рассказали. Каким образом диаграммы Венна покажут пересечение ключей при расчёте накопительного итога?


Да по этому итогу я кстати и ответил.
Отличная визуализация. Если в клетках пересечения, не удовлетворяющих условию (которые Вы не раскрашиваете), не писать чисел, восприниматься будет еще лучше.

Кажется мне, проблема веб-разработчиков, отвечающих на вопросы по SQL скорее в том, что у людей нет интуитивного понимания концепций SQL. Мы просто не встречаем их в быту. И без опыта близкого общения с базой, многие вещи принимаются интуитивно на основе похоже звучащих (выглядящих) бытовых концептов, и соответственно, не правильно. Плюс туториалы и объяснения «на пальцах».

В целом, про что ни спроси в плане SQL и реляционных баз, чаще всего в ответ получишь логично звучащее, но неверное мнение. И не было бы в этом ничего странного (технология старая и довольно сложная), если бы язык запросов не назывался Simple Query Language.

Боюсь, что в предыдущей статье мой комментарий потеряется, поэтому пишу здесь.

Вроде же sql — structured query language, язык структурированных запросов.

Большое спасибо за ответ. Это отличный пример интуитивного, логичного, но неверного понимания SQL.

Мне кажется, что zetroot имел в виду, что аббревиатура SQL расшифровывается как Structured Query Language, а не как Simple Query Language. Что есть абсолютная правда, см. например https://en.wikipedia.org/wiki/SQL

Зачем изобретать колесо, с точки зрения, ученика — диаграммы Венна — ясны и понятны, кому это не нужно — останутся с приблизительным пониманием, кто решит углубить свои знания со всем разберется… Не надо изобретать то, что изобретать не надо.
Да вы просто гений. Спасибо большое — очень помог такой способ визуализации. Добавил в закладки, плюсануть не могу — карма низкая :)
«Гений» — это уж слишком, но если кто плюсанет статью, будет и правда здорово

Согласен с Сергеем - вы придумали отличную визуализацию.

И теперь я понял, почему джойн для вашего примера с едингичками даёт 4 строки а не 2.
Спасибо вам!

Визуализацию нужно повернуть на 45 градусов, и поменять в ней таблицы местами.


Вроде бы получилась простая визуализация. Хотя в ней есть ограничения: здесь показан случай, когда в ON записано равенство, а не что-то хитрое (любое булево выражение).

Отличие "любого булева выражения" от равенства — лишь в том, что "любые булевы выражения" чаще дают дублирующиеся строки. Но поскольку вы специально подобрали совпадающие идентификаторы — никакого отличия в визуализации не будет.

ИМХО — нет никакой трагедии в том, чтобы использовать диаграммы Венна. С одним условием — уточнять, что они применимы только для ключей (точнее, для unique полей). В случае же дубликатов схема другая. Да и все.

Диаграммы просты и понятны, а JOIN, ИМХО, в 99% случаев идет по ключу. Не знаю, как у других, а у меня лично за 20 лет программирования ни разу не возникла необходимость использовать какие-то другие поля.

Это, примерно, как с математикой — в школе нас несколько лет учат, что квадратный корень из отрицательного числа взять нельзя, а в институте внезапно появляется мнимая единица.
Диаграммы Венна тут вторичны. Первичен вопрос о том есть ли пересечение и что именно пересекается в случае JOIN (если JOIN понимать буквально как JOIN то есть соединение а не как фильтр по всему чему угодно).

Кстати, а как же FULL OUTER JOIN? Ну так, чисто для полноты картины.

Извините что я отправляю в Вики, но там все случаи описаны en.wikipedia.org/wiki/Relational_algebra Просто прежде чем дойти до формального определения FULL OUTER JOIN нужна вся предыстория. В случае с простым JOIN все более интуитивно понятно (если повторюсь под JOIN понимать только JOIN)
Вот запоминают джуны всякие картинки, а суть всё равно утекает. Далее канонического описания уйти не могут.
Самый банальный вопрос, на котором многие тупят на собеседовании — что будет, если среди значений попадётся null?
И хорошо, если сумеет вспомнить, что по стандарту null не равен ничему. Но сумеет ли домыслить результат?
Часто может для left join получить вот такую табличку:

bad left join

А должен был бы получить:

good left join

И даже если нарисует, поймёт ли, почему так? Что там ещё сокрыто под этими null-ми?

Куда нагляднее, если добавить ещё один столбец с данными и посмотреть на результат (кстати, многие осилив пример из статьи, сливаются на таком простом усложнении):

CREATE TABLE t1 (id int, v varchar(1));
CREATE TABLE t2 (id int, v varchar(1));

INSERT INTO t1
values
(1, 'a'),
(null, 'b'),
(1, 'c'),
(6, 'd'),
(5, 'e'),
(null, 'f');

INSERT INTO t2
VALUES
(1, 'a'),
(1, 'b'),
(2, 'c'),
(null, 'd'),
(3, 'e'),
(5, 'f'),
(null, 'g');

SELECT t1.id, t2.id
FROM t1 
    LEFT JOIN t2
            ON t1.id = t2.id;
    
SELECT t1.v, t2.v
FROM t1 
    LEFT JOIN t2
            ON t1.id = t2.id;


Первый select вернёт данные для второй картинки:


А что вернёт второй select?


Что в виде наглядной таблички выглядит так:


Вот простенькая визуализация по сабжу — две частично пересекающиеся таблицы и full join, inner join, left join, левое исключение:
image
image
image
image
у меня картинки не подгрузились
Странно, а на репетиции все получалось. Хорошо, вот картинки с радикала — две частично пересекающиеся таблицы и full join, inner join, left join, левое исключение:
image
image
image
image
Мой любимий цикл статей с 2к13
join — это скорее декартово произведение, чем пересечение.

Не просто «скорее»: соединение как раз и определяется как декартово произведение, к которому применена выборка по указанному условию соединения. В SQL это легко увидеть, например:
SELECT t1.id, t2.id
FROM t1 
    INNER JOIN t2
        ON t1.id = t2.id

эквивалентно декартовому произведению с условием:
SELECT t1.id, t2.id
FROM t1, t2
    WHERE t1.id = t2.id

или используем альтернативный синтаксис с CROSS JOIN:
SELECT t1.id, t2.id
FROM t1
    CROSS JOIN t2
        WHERE t1.id = t2.id

Так и хочеться набросить что web девелоперы не могут в алгебру, но собственно вот из учебных материалов:

http://www.mstu.edu.ru/study/materials/zelenkov/ch_4_4.html

  • СОЕДИНЕНИЕ

  • Данная операция имеет сходство с ДЕКАРТОВЫМ ПРОИЗВЕДЕНИЕМ. Однако, здесь добавлено условие, согласно которому вместо полного произведения всех строк в результирующее отношение включаются только строки, удовлетворяющие опредленному соотношению между атрибутами соединения (А1,A2) соответствующих отношений.

    И да, что у вас там в постгре лежит и почему вы джойните диапазоны ipшников - это конечно отдельный вопрос

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории