Ученик обещал заплатить за обучение, но только если выиграет свой первый судебный процесс.
Неопределённость. Первый процесс, где он защищает обвиняемого, где он является обвиняемым, или любой? Ученик опять же может нанять и другого защитника - тогда даже в случае положительного для него решения суда он является не выигравшим, а невиновным.
Теперь развернём NOT IN в то, чем он работает под капотом. x IN (a, b, c) — это сокращение для x = a OR x = b OR x = c. Соответственно, x NOT IN (a, b, c) — это NOT (x = a OR x = b OR x = c), по законам логики — x <> a AND x <> b AND x <> c.
Кстати.. вот сижу и думаю - а применимы ли тут законы бинарной логики?
Аргументом NOT IN чаще является подзапрос, а не список значений. Этот подзапрос может иметь источником несколько таблиц с OUTER JOIN - вот вам и потенция для NULL.
Теперь развернём NOT IN в то, чем он работает под капотом. x IN (a, b, c) — это сокращение для x = a OR x = b OR x = c. Соответственно, x NOT IN (a, b, c) — это NOT (x = a OR x = b OR x = c), по законам логики — x <> a AND x <> b AND x <> c.
Предлагаю изменить форматирование и сделать вот это вот всё крупным, ярким и ну очень выделенным, чтобы сразу бросалось в глаза. Может быть, даже оформить это как отдельный раздел, а не как рядовой фрагмент внутри раздела. Потому что именно это - объяснение, а всё остальное - просто антураж.
Не-не... вы ушли далеко в сторону. Где у вас "повторность разворачивания сложной логики", о которой я изначально спрашивал (что собсно и породило эту ветку)?
С тем, что материализация иной раз может быть полезна, мне даже в голову не приходит спорить.
Реляционная модель изначально НЕ предназначалась для обработки иерархических (древовидных) структур данных.
Да ладно.. Ещё самые первые БД уже вовсю хранили и обрабатывали self-referenced entities (те же parent-child), а это не что иное как иерархия. Другое дело, что поначалу возможности SQL были узки, и графы (иерархия - частный случай графа) обрабатывались либо хранимыми процедурами, либо вообще внешним кодом. Реляционной модели по большому счёту вообще сиренево, что именно хранить - плоские отношения или иерархические.
К слову, MS SQL 7.0 уже поддерживал и хранимые процедуры, и временные таблицы, и операторы управления выполнением (WHILE, IF), так что не было никакой необходимости волочь обработку на клиента. Мне, конечно, "разруливать изделие из сотни деталей от корня" не приходилось, но полная ресурсная модель строительства дома (скажем, 12 этажей 8 подъездов), полагаю, слегка поболе будет.
Они же рациональные, причём все. И совершенно глупо считать, что Д в предложенном раскладе удовлетворится одной монетой. Во всяком случае, он должен рассуждать так: "Пока что мне светит либо 0 монет, либо 1 монета. Надо получить хотя бы 2. Если А даст мне 1 монету, а проголосую против него. Тогда Б, если не идиот, а он не идиот, должен понимать, что я и его прокачу точно так же и по тем же соображениям (тогда В мне просто обязан будет дать 1 монету, я ничего не теряю), и, чтобы этого избежать, даст мне минимум 2 монеты."
Обратите внимание еще на то, что в ORDER BY добавился id. Без него у строк 2 и 3 одинаковый ключ, и какая из них «была раньше» в построчном кадре, не определено. Для построчных расчётов ключ сортировки должен быть уникальным.
Ага... вот только это добавление сделало ненужным указание фрейма, потому что теперь по критерию сортировки все записи уникальны, и "RANGE вместо интуитивного ROWS" не стреляет.
И, кстати, расширение критерия сортировки до гарантированной уникальности ключа в общем случае является предпочтительным решением по сравнению с указанием фрейма - потому что гарантирует детерминированность результата. Впрочем, ниже вы об этом говорите. Но как-то слегка оторванно получается.
Как читать оконные функции в чужом коде
Я бы ещё добавил что-то вроде "как писать оконные функции в своём коде, который будут читать другие". И там бы предложил использовать не встроенное, а выделенное определение окон. Во-первых, дополнительно структурирует текст запроса, во-вторых, иной раз становится видно, что некоторые окна - лишние. Пример.
Ааа... так вы не о фреймворках, а о визуальных средствах построения запросов! Так это же считай тот же SQL писать, только не с клавиатуры, а мышкой, и весь сервис там - просто специальным образом организованная подстановка имён объектов.
Хотел бы я посмотреть, как в таком дерзайнере будет выглядеть запрос с латеральным связыванием, или просто с рекурсивным CTE..
А мне и не надо именно пользоваться. Достаточно тем на форумах, типа "Я написал вот такой код, а он превратился вот в такой SQL, и всё тормозит, как девяносто пятая". А внутри (N+1)*M или ещё какая беда.
В контексте назначения статьи всё корректно и пользы от такой формулировки для обучающегося будет больше, нежели от набивания его памяти ненужными на данном этапе возможными деталями и вариантами.
Я вообще-то, наоборот, ратую не за добивание ненужными сведениями, а за удаление спорных. В частности, за то, что вставка "Важный нюанс для Хабра" - (безусловно) вредна для начинающего. И что слова про "никогда не передаст" - не единственные спорные в этом предложении.
Ну так и не надо провокационных фраз о том, что роутер в принципе не передаёт. Особенно таких фраз, которые могут, а по незнанию скорее всего и будут, поняты неправильно. А то ведь потом - переучиваться, а это больно, особенно если на своих ошибках.
VPN-шлюз передаёт МАС - кому? роутеру, аднака. А уж роутер - дальше, наружу. Кстати, VPN вполне имеет право и не шифровать трафик, смотря как и для чего настроен.
Эммм... вы имеете в виду, что некое начальное представление со сравнительно общей агрегацией будет материализовано, а потом на него будут накладываться дополнительные группировки, сортировки и прочие фильтры в соответствии с разными частными выражениями? Мне как-то это несколько сомнительно - даже в части FILTER, а уж по остальным вариациям так и вовсе не верится.
Это никоим образом не делает допустимым сообщение ложных сведений и выдачу их за истинные. Сперва нужно продумать формулировку или рассмотреть аналогию со всех сторон, и если найдена такого рода погрешность - она должна быть устранена, вплоть до изъятия фразы из текста. Может, тот, "кто только-только пытается понять разницу между IP и MAC", сегодня и скажет "Спасибо".. но когда он немножко разберётся в теме, баланс благодарностей и проклятий в вашей карме (я не про карму на Хабре, если что) имеет шанс изрядно понизиться.
Детский сад. Ну или ладно, средняя школа - это там последний раз нам говорили, что на ноль делить ну никак нельзя.
Ну вот, например (выбрал самый понятный, в том числе для непродвинутого читателя, пример):
Важный нюанс для Хабра: MAC-адреса работают только в пределах локальной сети. Ваш домашний роутер никогда не передаст ваш MAC-адрес дальше, провайдеру или серверу Хабра. Как только ваши данные выходят за пределы квартиры — в игру вступает IP-адрес. И это тема нашего следующего раздела.
Подключаю я, значит, свой домашний роутер из дома к роутеру на работе, поднимая между ними VPN, лезу со своего компа на рабочий сервер, а тот мне и говорит: "А я, между прочим, знаю МАС твоей рабочей станции, мне его твой роутер переслал, и даже не поморщился.".
Я бы сказал, что с этим запросом всё ещё хуже. Априорно почему-то и автор, и вы за ним, предполагаете, чтоboss_id не может содержать значение, отсутствующее в id (в том числе NULL - у нас же "числиться в отделе" и "работать в отделе" вовсе не одно и то же) - но это ровным счётом ниоткуда не следует. А из-заINNER JOIN такие сотрудники не попадут в выходной набор, но их зряплата будет учтена при расчёте средней - то есть в общем случае задача-то решена неправильно.
Ошибаетесь. Материализация гарантирует, что одна и та же запись получит один и тот же результат вычисления функции, вне зависимости от количества последующих обращений к нумерующему CTE. А вот инлайнинг такой гарантии не даст.
Детерминация сортировки может быть и не нужна. Например, полученный в CTE номер может быть использован для связывания результатов обработки пронумерованных записей в последующих CTE. И тут абсолютно по барабану, насколько криво записи отнумерованы - главное, что номера уникальны, и во всех производных записях одинаковы для одной и той же исходной. Расширение же критерия сортировки до уникального просто утяжелит и замедлит запрос, не давая ну вообще никакого профита.
Неопределённость. Первый процесс, где он защищает обвиняемого, где он является обвиняемым, или любой? Ученик опять же может нанять и другого защитника - тогда даже в случае положительного для него решения суда он является не выигравшим, а невиновным.
Кстати.. вот сижу и думаю - а применимы ли тут законы бинарной логики?
Аргументом NOT IN чаще является подзапрос, а не список значений. Этот подзапрос может иметь источником несколько таблиц с OUTER JOIN - вот вам и потенция для NULL.
Предлагаю изменить форматирование и сделать вот это вот всё крупным, ярким и ну очень выделенным, чтобы сразу бросалось в глаза. Может быть, даже оформить это как отдельный раздел, а не как рядовой фрагмент внутри раздела. Потому что именно это - объяснение, а всё остальное - просто антураж.
Не-не... вы ушли далеко в сторону. Где у вас "повторность разворачивания сложной логики", о которой я изначально спрашивал (что собсно и породило эту ветку)?
С тем, что материализация иной раз может быть полезна, мне даже в голову не приходит спорить.
Да ладно.. Ещё самые первые БД уже вовсю хранили и обрабатывали self-referenced entities (те же parent-child), а это не что иное как иерархия. Другое дело, что поначалу возможности SQL были узки, и графы (иерархия - частный случай графа) обрабатывались либо хранимыми процедурами, либо вообще внешним кодом. Реляционной модели по большому счёту вообще сиренево, что именно хранить - плоские отношения или иерархические.
К слову, MS SQL 7.0 уже поддерживал и хранимые процедуры, и временные таблицы, и операторы управления выполнением (WHILE, IF), так что не было никакой необходимости волочь обработку на клиента. Мне, конечно, "разруливать изделие из сотни деталей от корня" не приходилось, но полная ресурсная модель строительства дома (скажем, 12 этажей 8 подъездов), полагаю, слегка поболе будет.
А теперь сделайте следующий логический шаг. И учитывайте, что А не хочет оказаться за бортом.
Они же рациональные, причём все. И совершенно глупо считать, что Д в предложенном раскладе удовлетворится одной монетой. Во всяком случае, он должен рассуждать так: "Пока что мне светит либо 0 монет, либо 1 монета. Надо получить хотя бы 2. Если А даст мне 1 монету, а проголосую против него. Тогда Б, если не идиот, а он не идиот, должен понимать, что я и его прокачу точно так же и по тем же соображениям (тогда В мне просто обязан будет дать 1 монету, я ничего не теряю), и, чтобы этого избежать, даст мне минимум 2 монеты."
И это только самое начало рассуждений.
Ага... вот только это добавление сделало ненужным указание фрейма, потому что теперь по критерию сортировки все записи уникальны, и "RANGE вместо интуитивного ROWS" не стреляет.
И, кстати, расширение критерия сортировки до гарантированной уникальности ключа в общем случае является предпочтительным решением по сравнению с указанием фрейма - потому что гарантирует детерминированность результата. Впрочем, ниже вы об этом говорите. Но как-то слегка оторванно получается.
Я бы ещё добавил что-то вроде "как писать оконные функции в своём коде, который будут читать другие". И там бы предложил использовать не встроенное, а выделенное определение окон. Во-первых, дополнительно структурирует текст запроса, во-вторых, иной раз становится видно, что некоторые окна - лишние. Пример.
Ааа... так вы не о фреймворках, а о визуальных средствах построения запросов! Так это же считай тот же SQL писать, только не с клавиатуры, а мышкой, и весь сервис там - просто специальным образом организованная подстановка имён объектов.
Хотел бы я посмотреть, как в таком дерзайнере будет выглядеть запрос с латеральным связыванием, или просто с рекурсивным CTE..
А мне и не надо именно пользоваться. Достаточно тем на форумах, типа "Я написал вот такой код, а он превратился вот в такой SQL, и всё тормозит, как девяносто пятая". А внутри (N+1)*M или ещё какая беда.
Я вообще-то, наоборот, ратую не за добивание ненужными сведениями, а за удаление спорных. В частности, за то, что вставка "Важный нюанс для Хабра" - (безусловно) вредна для начинающего. И что слова про "никогда не передаст" - не единственные спорные в этом предложении.
Ну так и не надо провокационных фраз о том, что роутер в принципе не передаёт. Особенно таких фраз, которые могут, а по незнанию скорее всего и будут, поняты неправильно. А то ведь потом - переучиваться, а это больно, особенно если на своих ошибках.
VPN-шлюз передаёт МАС - кому? роутеру, аднака. А уж роутер - дальше, наружу. Кстати, VPN вполне имеет право и не шифровать трафик, смотря как и для чего настроен.
Эммм... вы имеете в виду, что некое начальное представление со сравнительно общей агрегацией будет материализовано, а потом на него будут накладываться дополнительные группировки, сортировки и прочие фильтры в соответствии с разными частными выражениями? Мне как-то это несколько сомнительно - даже в части FILTER, а уж по остальным вариациям так и вовсе не верится.
Главное - это случайно не посмотреть, что за готовый текст сгенерировал такой инструмент. Иначе психотравма практически гарантирована.
Это никоим образом не делает допустимым сообщение ложных сведений и выдачу их за истинные. Сперва нужно продумать формулировку или рассмотреть аналогию со всех сторон, и если найдена такого рода погрешность - она должна быть устранена, вплоть до изъятия фразы из текста. Может, тот, "кто только-только пытается понять разницу между IP и MAC", сегодня и скажет "Спасибо".. но когда он немножко разберётся в теме, баланс благодарностей и проклятий в вашей карме (я не про карму на Хабре, если что) имеет шанс изрядно понизиться.
Детский сад. Ну или ладно, средняя школа - это там последний раз нам говорили, что на ноль делить ну никак нельзя.
Ну вот, например (выбрал самый понятный, в том числе для непродвинутого читателя, пример):
Подключаю я, значит, свой домашний роутер из дома к роутеру на работе, поднимая между ними VPN, лезу со своего компа на рабочий сервер, а тот мне и говорит: "А я, между прочим, знаю МАС твоей рабочей станции, мне его твой роутер переслал, и даже не поморщился.".
Я бы сказал, что с этим запросом всё ещё хуже. Априорно почему-то и автор, и вы за ним, предполагаете, что
boss_idне может содержать значение, отсутствующее вid(в том числе NULL - у нас же "числиться в отделе" и "работать в отделе" вовсе не одно и то же) - но это ровным счётом ниоткуда не следует. А из-заINNER JOINтакие сотрудники не попадут в выходной набор, но их зряплата будет учтена при расчёте средней - то есть в общем случае задача-то решена неправильно.Вы смогли понять, что такое "повторно"? Поделитесь, а..
Ошибаетесь. Материализация гарантирует, что одна и та же запись получит один и тот же результат вычисления функции, вне зависимости от количества последующих обращений к нумерующему CTE. А вот инлайнинг такой гарантии не даст.
Детерминация сортировки может быть и не нужна. Например, полученный в CTE номер может быть использован для связывания результатов обработки пронумерованных записей в последующих CTE. И тут абсолютно по барабану, насколько криво записи отнумерованы - главное, что номера уникальны, и во всех производных записях одинаковы для одной и той же исходной. Расширение же критерия сортировки до уникального просто утяжелит и замедлит запрос, не давая ну вообще никакого профита.