Comments 17
Соответственно, 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)
Всё, что нужно - это в правильных местах размещать условия связывания и следить за видимостью и текущими алиасами.
Не очень понял, что вы имели ввиду. Я про
t1
left outer join (
t2
inner join t3 on ...
) on ...
например
Я именно про это. В вашем случае высший приоритет у скобки, и сперва связываются t2 и t3, а потом t1 связывается с полученным результатом. И, с учётом приоритета и видимости, в условии связывания t2 и t3 нельзя использовать поля из t1, ибо получим unknown table.
Ради любопытства - разберите порядок связывания и области видимости в источнике
FROM t1, t2 JOIN (t3 JOIN t4, t5 JOIN t6)
Ну и ещё неявно про разницу между FROM t1 CROSS JOIN t2
и FROM t1, t2
. Сколько раз встречал вопросы типа: почему FROM t1 CROSS JOIN t2 INNER JOIN t3 ON t3.x=t1.x AND t3.y=t2.y
работает, а FROM t1, t2 INNER JOIN t3 ON t3.x=t1.x AND t3.y=t2.y
приводит к ошибке.
В данном месте скобочки нужны ИСКЛЮЧИТЕЛЬНО человеку. Их можно смело выкинуть.
Это не всегда верно. Если их просто выкинуть и не вносить иных правок, то большинство СУБД выдаст ошибку синтаксиса из-за некорректного местоположения второго ON (или из-за отсутствия ON в первом JOIN - зависит от СУБД). Перемещение же второго ON в LEFT OUTER JOIN для получения синтаксически корректного кода выдаст ошибку, если в его выражении используются поля из t3.
В оригинальной документации по реляционным базам данных FROM, WHERE, GROUP BY, etc... называются не "statement" (оператор), а "clause" (параграф) есть и другие значения перевода, на параграф мне кажется наиболее приемлемым вариантом.
Мне кажется достаточно удачным для перевода clause использование термина "секция". И чуть менее удачным - "раздел".
Можно итак, но никак не "оператор". Потому что SELECT это оператор, а FROM, WHERE ... это его части. Я в разговоре всегда называю это слово как есть "клауз" поскольку оно всегда идет с WHERE, FROM, GROUP BY ... и "клауз". В тексте так будет не красиво поэтому "секция WHERE" будет гораздо лучше. А еще уместно было бы писать, да и говорить, "фраза WHERE". В линвистике clause переводится как "придаточное предложение". Но это длинно.
Кстати в русском переводе М.З. Когаловского от 1988 года книги "A Guide to DB2" автора K. Deit используется слово "фраза". Думаю этот факт окончательно решает вопрос как переводить "clause".
Успешно отбившись от атаки NoSQL баз данных, реляционные СУБД доминируют на рынке уже порядка 40 лет ...
Лет этак на 10 раньше на самом деле. Из Википедии:
"DB2 берет свое начало в начале 1970-х годов, когда Эдгар Ф. Кодд, исследователь, работавший в IBM, описал теорию реляционных баз данных, а в июне 1970 года опубликовал модель для обработки данных.
В 1974 году исследовательский центр IBM в Сан-Хосе разработал связанную систему управления базами данных (СУБД) под названием System R, чтобы реализовать концепции Кодда. Ключевой разработкой проекта System R стал язык структурированных запросов (SQL)."
Что касаемо атаки NoSQL баз данных. Будучи многолетним аппологетом Реляционных Баз Данных мне последние 2 года пришлось работать с NoSQL DB с названием IDMS. Cтрого говоря в этой БД два режима работы NoSQL (Network structure database) и SQL. Я работал с NoSQL режимом и некоторых возможности этого режима мне показались весьма заманчивыми.
Дело в том что не все запросы к данным эффективно выполняются с исрользованием классической алгебры реляционных операций. Это проявляется в значительных отступлениях от классики и добавления в синтаксис SQL нетрадиционных параграфов (костылей). Кроме того приходилось иметь дело с очевидными извращениями в написаниях SQL запросов делающих из реляционной БД нечто совсем другое. Под такие запросы приходится подгонять и структуру данных, опять же делая из RDBMS нечто совсем другое формально оставаясь DB2, Oracle, MS SQL.
Доминирование чего-либо над чем-то не самым мудрый путь. Надо знать и понимать что из имеющегося для работы с данными наболее приемлемо для решения конкретной задачи.
Вполне разумно сочетать использования БД разной архитектуры в одном проекте. Т.е. иметь и брать лучшее из каждой для разного применения и разных требований. На самом деле имеется порочная практика бросания из крайности в крайность.
Учимся читать SQL SELECT