Comments 9
Соответственно, HAVING работает аналогично WHERE — принимает на вход таблицу и порождает на выход таблицу с такими же (разбитыми на две группы) атрибутами, все строки которой соответствуют определённому условию.
Вообще-то не аналогично
Having работает с результатом
Where работает до выборки
Сначала мне не понравилось как написано, из-за разных не точностей. Но почитав побольше мне показалось, что эти не точности формируют систему обучения и позволяют отступить от правильного классического объяснения и показать саму суть и смысл работы sql - "конвеера". А для начального знакомства - это важнее, чем точность. В итоге мне понравилась статья. Автор молодец.
Очень хорошая статья.
Я не знаю Kotlin, хотел спросить: ваша реализация группировки работает так: вы получаете списки строк, потом превращаете их в строки списков, и на последнем шаге для ключа группировки заменяете список одинаковых значений на единственное значение. Как с точки зрения проверки типов работает, что вы в мапу списков помещаете не список, а единственное значение? Я вижу, что groupedRow: Map<
String
, List<
Any
?>>
, но не понимаю, что такое делает + , что тип стал Map<String, Any>
Очень хорошая статья.
Спасибо:)
ак с точки зрения проверки типов работает, что вы в мапу списков помещаете не список, а единственное значение? Я вижу, что
groupedRow: Map<
String
, List<
Any
?>>
, но не понимаю, что такое делает + , что тип стал Map<String, Any>
List<Any?>
- является подтипом Any
.
"оператор" + - это на самом деле просто синтаксический сахар для создания копии мапы и добавления в неё элемента (копирование вместо добавления в имеющуюся - из-за ФП головного мозга)

Соответственно:
Метод
groupBy
возвращаетTable
akaList<Map<String, Any>>
Лямбда, которая передаётся в
rowGroups.map
возвращаетMap<String, List<Any?>>
А сам метод map возвращает
List<Map<String, List<Any?>>>
И при возврате из метода
groupBy
выполняется upcast (приведение к супертипу)List<Map<String, List<Any?>>>
->List<Map<String, Any>>
Господи, ну сколько же можно, не думая. переписывать одно и то же друг у друга, а?
Оператор FROM
Оператор JOIN
Оператор WHERE
Оператор GROUP BY
Оператор HAVING
Оператор ORDER BY
Операторы OFFSET и LIMIT
Оператор SELECT
Во-первых, у вас, как и у всех ваших предшественников, пропущен пункт "оконные функции". который НЕОБХОДИМО в таком списке указывать отдельно - масса проблем возникает именно из-за непонимания местоположения этого шага в формальном роадмапе исполнения запроса.
Во-вторых, у вас нет дополнительного описания того, где в этом списке находятся коррелированные, в т.ч. и латеральные, подзапросы.
Спасибо за статью.
Заметил опечатку в значении колонки de.training_budget во второй строке у "Маслова" после первого join. Выглядит так, что значение 40000 поместили к "Позднякову"

А ещё join-ы умеют объединяться вместе с помощью круглых скобочек.
Join - это самое обычное выражение, которое может включать три операции (в порядке снижения приоритета):
скобка
явный JOIN
запятая (неявный JOIN)
Всё, что нужно - это в правильных местах размещать условия связывания и следить за видимостью и текущими алиасами.
Учимся читать SQL SELECT