uz
Feedback

Firibgarlarga uchmang! Telemetrio bunday kanallarni topadi va belgilaydi 👉 Belgini ko‘rmoqchi bo‘lsangiz, obuna bo‘ling

Точка входа в программирование

Точка входа в программирование

Kanalga Telegram’da o‘tish

Фундаментальные знания по основам программирования Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels Сайт: https://tprg.ru/site Регистрация в перечне РКН: https://tprg.ru/zrgj

Ko'proq ko'rsatish

📈 Telegram kanali Точка входа в программирование analitikasi

Точка входа в программирование (@prog_point) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 17 911 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 7 267-o'rinni va Rossiya mintaqasida 36 747-o'rinni egallagan.

📊 Auditoriya ko‘rsatkichlari va dinamika

невідомо sanasidan buyon loyiha tez o‘sib, 17 911 obunachiga ega bo‘ldi.

25 Oktabr, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -91 ga, so‘nggi 24 soatda esa -6 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.

  • Tasdiqlash holati: Tasdiqlanmagan
  • Jalb etish (ER): Auditoriya o‘rtacha 3.35% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 2.21% ini tashkil etuvchi reaksiyalarni to‘playdi.
  • Post qamrovi: Har bir post o‘rtacha 600 marta ko‘riladi; birinchi sutkada odatda 396 ta ko‘rish yig‘iladi.
  • Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 2 ta reaksiya keladi.
  • Tematik yo‘nalishlar: Kontent docker, javascript, kubernetes, браузер, контейнер kabi asosiy mavzularga jamlangan.

📝 Tavsif va kontent siyosati

Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“Фундаментальные знания по основам программирования Разместить рекламу: @tproger_sales_bot Правила общения: https://tprg.ru/rules Другие каналы: @tproger_channels Сайт: https://tprg.ru/site Регистрация в перечне РКН: https://tprg.ru/zrgj”

Yuqori yangilanish chastotasi (oxirgi ma’lumot 26 Oktabr, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.

17 911
Obunachilar
-624 soatlar
-187 kun
-9130 kun
Obunachilarni jalb qilish
Okt '26
Oktabr '26
+107
10 kanalda
Sentabr '26
+64
8 kanalda
Get PRO
Avgust '26
+63
6 kanalda
Get PRO
Iyul '26
+23
4 kanalda
Get PRO
Iyun '26
+47
1 kanalda
Get PRO
May '26
+58
1 kanalda
Get PRO
Aprel '26
+54
3 kanalda
Get PRO
Mart '26
+55
5 kanalda
Get PRO
Fevral '26
+64
4 kanalda
Get PRO
Yanvar '26
+72
2 kanalda
Get PRO
Dekabr '25
+115
5 kanalda
Get PRO
Noyabr '25
+83
5 kanalda
Get PRO
Oktabr '25
+140
3 kanalda
Get PRO
Sentabr '25
+81
4 kanalda
Get PRO
Avgust '25
+81
3 kanalda
Get PRO
Iyul '25
+96
3 kanalda
Get PRO
Iyun '25
+148
8 kanalda
Get PRO
May '25
+96
3 kanalda
Get PRO
Aprel '25
+76
3 kanalda
Get PRO
Mart '25
+187
8 kanalda
Get PRO
Fevral '25
+179
5 kanalda
Get PRO
Yanvar '25
+153
3 kanalda
Get PRO
Dekabr '24
+178
4 kanalda
Get PRO
Noyabr '24
+136
5 kanalda
Get PRO
Oktabr '24
+130
8 kanalda
Get PRO
Sentabr '24
+129
5 kanalda
Get PRO
Avgust '24
+145
4 kanalda
Get PRO
Iyul '24
+94
2 kanalda
Get PRO
Iyun '24
+71
4 kanalda
Get PRO
May '24
+174
5 kanalda
Get PRO
Aprel '24
+208
7 kanalda
Get PRO
Mart '24
+131
4 kanalda
Get PRO
Fevral '24
+127
1 kanalda
Get PRO
Yanvar '24
+141
3 kanalda
Get PRO
Dekabr '23
+106
5 kanalda
Get PRO
Noyabr '23
+115
3 kanalda
Get PRO
Oktabr '23
+108
1 kanalda
Get PRO
Sentabr '23
+134
0 kanalda
Get PRO
Avgust '23
+250
0 kanalda
Get PRO
Iyul '23
+282
0 kanalda
Get PRO
Iyun '23
+360
0 kanalda
Get PRO
May '23
+475
0 kanalda
Get PRO
Aprel '23
+543
0 kanalda
Get PRO
Mart '23
+424
0 kanalda
Get PRO
Fevral '23
+536
0 kanalda
Get PRO
Yanvar '23
+1 067
0 kanalda
Get PRO
Dekabr '22
+487
0 kanalda
Get PRO
Noyabr '22
+564
0 kanalda
Get PRO
Oktabr '22
+384
0 kanalda
Get PRO
Sentabr '22
+612
0 kanalda
Get PRO
Avgust '22
+494
0 kanalda
Get PRO
Iyul '22
+587
0 kanalda
Get PRO
Iyun '22
+969
0 kanalda
Get PRO
May '22
+621
0 kanalda
Get PRO
Aprel '22
+425
0 kanalda
Get PRO
Mart '22
+773
0 kanalda
Get PRO
Fevral '22
+1 309
0 kanalda
Get PRO
Yanvar '22
+558
0 kanalda
Get PRO
Dekabr '21
+353
0 kanalda
Get PRO
Noyabr '21
+2 297
0 kanalda
Get PRO
Oktabr '21
+1 689
0 kanalda
Get PRO
Sentabr '21
+324
0 kanalda
Get PRO
Avgust '21
+837
0 kanalda
Get PRO
Iyul '21
+1 025
0 kanalda
Get PRO
Iyun '21
+627
0 kanalda
Get PRO
May '21
+769
0 kanalda
Get PRO
Aprel '21
+2 906
0 kanalda
Get PRO
Mart '21
+882
0 kanalda
Get PRO
Fevral '21
+2 017
0 kanalda
Get PRO
Yanvar '21
+9 289
0 kanalda
Sana
Obunachilarni jalb qilish
Esdaliklar
Kanallar
26 Oktabr0
25 Oktabr+2
24 Oktabr+3
23 Oktabr0
22 Oktabr+7
21 Oktabr+6
20 Oktabr+1
19 Oktabr+2
18 Oktabr+2
17 Oktabr+2
16 Oktabr0
15 Oktabr+4
14 Oktabr+4
13 Oktabr+7
12 Oktabr+7
11 Oktabr+2
10 Oktabr0
09 Oktabr+6
08 Oktabr+4
07 Oktabr+12
06 Oktabr+8
05 Oktabr+10
04 Oktabr0
03 Oktabr+9
02 Oktabr+1
01 Oktabr+8
Kanal postlari
Один знак в Bash решает, дописать файл или стереть старый текст Знак > отправляет обычный вывод команды в файл. Если файла нет, Bash создаст его, а существующий обнулит перед записью. У >> другое поведение: добавить в конец. Проверьте на новом файле notes.txt в отдельной учебной папке. 1️⃣ Запишите первую строку, затем добавьте вторую:
printf 'first\n' > notes.txt
printf 'second\n' >> notes.txt
cat notes.txt
cat покажет first и second на отдельных строках. Сами команды printf отправили текст в файл, поэтому в терминале он появился только после cat. 2️⃣ Повторите запись с одним знаком:
printf 'third\n' > notes.txt
cat notes.txt
Останется только third. Это пример для Bash с выключенной защитой noclobber: при включённой защите перезапись существующего обычного файла через > завершится ошибкой. Обе операции описаны в руководстве Bash.

2
Ноль может исчезнуть из-за значения по умолчанию Вы задали количество повторов 0, чтобы ничего не запускать. Но выражение 0 || 10 подставит десять. Оператор || выбирает правую часть, когда левая при проверке условия считается ложной. К таким значениям относятся и ноль, и пустая строка, и false. console.log(0 || 10) // 10 console.log(0 ?? 10) // 0 console.log(null ?? 10) // 10 Оператор ?? подставляет правую часть только вместо null или undefined. Поэтому для настройки, где ноль допустим, он сохраняет смысл значения. Пустую строку и false он тоже оставит. При этом ?? не проверяет правильность числа и не исправляет NaN. В первых двух строках замените ноль на false, затем на undefined. В первом случае результаты разойдутся, во втором оба будут 10. Выбор оператора зависит от того, что вы считаете отсутствующим значением. В примерах MDN можно сравнить остальные случаи.
387
3
Три строки в таблице, но COUNT(email) возвращает два У одного пользователя есть адрес, у второго — NULL, то есть отсутствие значения, у третьего — пустая строка. Запустите этот запрос в SQLite. WITH здесь задаёт учебный набор строк для одного запроса: WITH users(email) AS ( VALUES ('a@example.test'), (NULL), ('') ) SELECT COUNT(*) AS rows_total, COUNT(email) AS emails_present FROM users Получатся 3 и 2. По правилам COUNT в SQLite, COUNT(*) считает все строки, а COUNT(email) — только те, где значение не NULL. Пустая строка в SQLite считается значением, поэтому она тоже попала в счётчик. Это ещё не количество корректных почтовых адресов. Поменяйте ('') на (NULL): строк по-прежнему три, но второй счётчик станет равен одному. А если добавить в конец запроса WHERE 1 = 0, выборка будет пустой и оба счётчика вернут ноль.
443
4
lstrip может откусить часть нужного текста Из строки нужно убрать имя автора в начале. Кажется, что lstrip("Arthur: ") подходит, но результат неожиданно короткий: text = "Arthur: three!" print(text.lstrip("Arthur: ")) # ee! print(text.removeprefix("Arthur: ")) # three! Аргумент lstrip — набор отдельных символов для удаления слева. Метод идёт до первого символа вне набора, поэтому после имени съедает ещё t, h и r. removeprefix удаляет ровно один совпавший префикс, то есть заданное начало строки. Он доступен с Python 3.9. Оба метода возвращают результат, исходная строка text не меняется. Передайте им просто "three!". Первый снова оставит "ee!", второй вернёт "three!", потому что нужного префикса нет. А из "Arthur: Arthur: three!" второй удалит только первое имя. Это различие разобрано в документации строк Python.
440
5
Раскрывающийся ответ на HTML без JavaScript Для вопроса с ответом, который появляется по нажатию, достаточно двух HTML-элементов. Сохраните этот фрагмент в answer.html и откройте файл в браузере: <details> <summary>Где хранится ответ?</summary> <p>Внутри details.</p> </details> details содержит весь блок, а первый дочерний summary — его видимый заголовок. Нажатие на заголовок раскрывает и сворачивает ответ. Обработчик клика для этого примера писать не нужно. Теперь замените открывающий тег на <details open="false">. Вопреки названию значения, блок начнёт раскрытым. open — булев атрибут: важно само его наличие. Чтобы снова начать со свёрнутого ответа, уберите атрибут целиком. В учебнике web.dev показано, как связаны эти элементы и состояние блока.
458
6
Почему у backup.tar.gz расширение .gz, а основа — backup.tar В имени файла может быть несколько точек. Модуль pathlib в Python помогает разобрать его без ручного разрезания строки. PurePosixPath работает с записью пути в стиле Unix и для этого не обращается к диску: from pathlib import PurePosixPath p = PurePosixPath("backup.tar.gz") print(p.name) # backup.tar.gz print(p.stem) # backup.tar print(p.suffix) # .gz print(p.suffixes) # ['.tar', '.gz'] name — полное имя последней части пути. stem отбрасывает только последний суффикс, а suffixes собирает их список. Эти свойства не переименовывают файл и не проверяют его содержимое: имя с .gz ещё не доказывает, что перед вами архив. Замените имя на README: основа останется README, суффикс будет пустой строкой, список суффиксов — []. Другие варианты есть в справочнике pathlib.
442
7
Обычный метод получает объект, classmethod получает класс, а staticmethod обходится без них Класс описывает устройство объект
Обычный метод получает объект, classmethod получает класс, а staticmethod обходится без них Класс описывает устройство объектов, а экземпляр — конкретный объект этого класса. Например, класс Pizza и отдельная приготовленная пицца. У методов есть три варианта: class Pizza: def describe(self): return self.name @classmethod def create(cls, name): pizza = cls() pizza.name = name return pizza @staticmethod def valid_name(name): return bool(name.strip()) describe работает с конкретной пиццей через self. create получает класс через cls и создаёт его экземпляр. valid_name проверяет строку: ни объект, ни класс ей не передаются автоматически. Запись с @ — декоратор, который здесь задаёт способ вызова метода. В руководстве с примером Pizza эти различия показаны подробнее. Не каждой вспомогательной функции нужен staticmethod: иногда её удобнее оставить обычной функцией модуля.
489
8
Связный список хранит порядок элементов через ссылки между узлами Узел содержит значение и ссылку на следующий узел. Чтобы пр
Связный список хранит порядок элементов через ссылки между узлами Узел содержит значение и ссылку на следующий узел. Чтобы пройти список, программа следует по этим ссылкам: const second = { value: "B", next: null }; const first = { value: "A", next: second }; for (let node = first; node !== null; node = node.next) { console.log(node.value); // A, затем B } Переменная first указывает на начало. Каждый переход node.next ведёт к следующему элементу. Значение null обозначает конец. В отличие от массива, здесь нельзя просто обратиться к элементу с нужным индексом: до него приходится добираться по цепочке. Вставка рядом с уже найденным узлом требует изменить несколько ссылок. Но поиск нужного места может занять проход по всему списку. Поэтому обещание «любая вставка за O(1)» вводит в заблуждение. В иллюстрированном руководстве по связным спискам есть упражнения на обход и изменение связей.
449
9
Запуск Python-файла и запуск модуля через -m по-разному находят код Команда python app.py запускает файл по указанному пути.
Запуск Python-файла и запуск модуля через -m по-разному находят код Команда python app.py запускает файл по указанному пути. В команде python -m shop.app интерпретатор ищет модуль app внутри пакета shop и запускает его. Модуль — это отдельная единица Python-кода, часто файл с расширением .py. Пакет объединяет модули. В обоих случаях у запускаемого кода значение __name__ будет "__main__". При обычном импорте оно содержит имя модуля. На этом основан знакомый шаблон: def main(): print("Программа запущена") if __name__ == "__main__": main() При запуске main() выполнится. При импорте файла функция определится, но этот блок её не вызовет. Остальной код верхнего уровня при импорте всё равно выполняется. В руководстве по запуску Python-кода разобраны оба способа. Если в проекте есть пакеты, сначала уточните, что вы запускаете: путь к файлу или имя модуля.
471
10
WHERE отбирает отдельные строки, а HAVING — результаты группировки Нужно найти классы, где средняя оценка не ниже восьми: SEL
WHERE отбирает отдельные строки, а HAVING — результаты группировки Нужно найти классы, где средняя оценка не ниже восьми: SELECT class_name, AVG(grade) AS avg_grade FROM results GROUP BY class_name HAVING AVG(grade) >= 8; GROUP BY собирает строки каждого класса в группу. AVG вычисляет среднее, а HAVING оставляет группы, которые прошли проверку. Если написать WHERE grade >= 8, получится другая задача: сначала исключить низкие оценки и только потом посчитать среднее по оставшимся. Например, у класса оценки 6 и 10. Среднее — 8. После такого WHERE останется только 10, и среднее станет 10. Держите в голове логический порядок: сначала источник строк, затем WHERE, группировка и HAVING. Это помогает понять, на каком этапе исчезают данные. В учебном разборе SQL-запросов есть небольшая база, запросы и таблицы с ответами.
544
11
Стек возвращает последний добавленный элемент, а очередь — первый В стек положили A, затем B. Первым извлечётся B. Этот поряд
Стек возвращает последний добавленный элемент, а очередь — первый В стек положили A, затем B. Первым извлечётся B. Этот порядок называют LIFO: последним пришёл — первым вышел. В очереди после тех же добавлений первым извлечётся A. Это FIFO: первым пришёл — первым вышел. На маленьких массивах JavaScript разницу можно увидеть так: const stack = ["A", "B"]; console.log(stack.pop()); // B const queue = ["A", "B"]; console.log(queue.shift()); // A Стек подходит для истории отмены действий: сначала отменяем последнее. Очередь — для обработки ожидающих задач по порядку поступления. Здесь массив помогает показать поведение. У большой очереди удаление первого элемента может требовать перемещения остальных, поэтому способ хранения тоже имеет значение. В разборе стека и очереди можно проследить операции по шагам и попробовать кольцевую очередь.
525
12
Переменная внутри функции может скрывать одноимённую переменную снаружи Посмотрите на два значения price: price = 100 def sho
Переменная внутри функции может скрывать одноимённую переменную снаружи Посмотрите на два значения price: price = 100 def show_price(): price = 80 print(price) show_price() # 80 print(price) # 100 Присваивание внутри функции создаёт локальное имя. Оно действует при выполнении этой функции и не меняет внешнюю переменную. Пространство имён — это соответствие имён объектам. Благодаря отдельным пространствам разные функции могут использовать price, result или count, не перезаписывая значения друг друга. Если имя не определено локально, Python ищет его дальше: в окружающих функциях, модуле, затем среди встроенных имён. Поэтому переменная с названием list может скрыть встроенный конструктор списка. В разборе пространств имён есть примеры порядка поиска. При чтении кода полезно каждый раз уточнять: к какому именно имени относится эта строка?
494
13
Чистая функция вычисляет результат без изменения внешних данных Функция получает сумму и скидку, возвращает новую сумму. Ей н
Чистая функция вычисляет результат без изменения внешних данных Функция получает сумму и скидку, возвращает новую сумму. Ей не нужно читать глобальную переменную или менять переданный объект: def discounted(total, percent): return total * (100 - percent) // 100 print(discounted(1000, 10)) # 900 Здесь суммы заданы целыми единицами, а результат округляется вниз. Это правило конкретного примера, а не универсальный способ расчёта денег. Функцию называют чистой, если результат зависит только от аргументов и вызов не создаёт наблюдаемых побочных эффектов: например, не меняет внешний список и не записывает файл. Такую функцию проще проверить: передали 1000 и 10 — ожидаем 900. Чтобы проверить вычисление, не приходится готовить базу или очищать глобальное состояние. В руководстве по функциональному подходу разбираются и другие приёмы. Начать можно с отделения вычислений от ввода, вывода и изменения данных.
579
14
Условие в WHERE может убрать строки, сохранённые LEFT JOIN Есть клиенты и их заказы. Нужно показать всех клиентов, а рядом —
Условие в WHERE может убрать строки, сохранённые LEFT JOIN Есть клиенты и их заказы. Нужно показать всех клиентов, а рядом — только оплаченные заказы. LEFT JOIN сохраняет клиента, даже если подходящего заказа нет. В колонках заказа тогда будет NULL — отсутствие значения. Условие оплаты можно включить в правило соединения: SELECT c.name, o.id FROM customers AS c LEFT JOIN orders AS o ON o.customer_id = c.id AND o.status = 'paid'; Если перенести проверку в WHERE o.status = 'paid', она начнёт отбирать строки уже после соединения. У клиента без подходящего заказа сравнение с NULL не даст истину, и строка исчезнет. В первом варианте мы выбираем, какие заказы присоединить. Во втором — какие строки оставить в результате. На маленьких таблицах эта разница хорошо видна в пошаговом разборе JOIN.
590
15
Git не может обновить ветку простым сдвигом, если история разошлась Вы сделали коммит локально, а коллега добавил другой комм
Git не может обновить ветку простым сдвигом, если история разошлась Вы сделали коммит локально, а коллега добавил другой коммит в общую ветку. Теперь у каждой стороны есть изменение, которого нет у другой: A──B ваша ветка └──C общая ветка Команда git pull --ff-only остановится: передвинуть указатель с B на C, сохранив обе линии как одну готовую историю, нельзя. Сначала выполните git status, чтобы увидеть несохранённые в коммитах изменения. Затем git fetch: он скачает сведения об общей истории, но не объединит её с вашей веткой. Дальше нужно выбрать способ объединения. Merge соединяет линии истории, сохраняя существующие коммиты. Rebase переносит ваши коммиты на новую основу и меняет их идентификаторы. В разборе расхождения веток есть пример обоих подходов. Уже опубликованные коммиты не стоит переносить через rebase без согласования с командой.
567
16
Как проверить, что переписанная функция не потеряла поведение Новая реализация короче и проходит обычный пример. Но сохранила
Как проверить, что переписанная функция не потеряла поведение Новая реализация короче и проходит обычный пример. Но сохранила ли она все свойства старой? def old(items): return sorted(items) def new(items): return sorted(set(items)) for case in ([], [2], [3, 1], [2, 2]): print(case, old(case) == new(case)) # Последняя проверка: False Обе функции сортируют числа, но новая заодно удаляет повторы. Такой побочный эффект легко пропустить, если тестировать только разные элементы. Подход называется дифференциальным тестированием: обе реализации получают одинаковые входы, а результаты сравниваются. Проверять можно и типы ошибок, порядок элементов, побочные действия. Старая версия тоже может ошибаться. Найденное отличие нужно сверить с требованиями, прежде чем объявлять ошибкой новой реализации. Как сравнивать две реализации
601
17
Почему цепочка Promise может заморозить страницу Таймер с нулевой задержкой не запускается немедленно. Сначала завершается те
Почему цепочка Promise может заморозить страницу Таймер с нулевой задержкой не запускается немедленно. Сначала завершается текущий код, затем обрабатываются ожидающие микрозадачи, включая обработчики Promise. console.log("A"); setTimeout(() => console.log("B"), 0); Promise.resolve() .then(() => console.log("C")) .then(() => console.log("D")); console.log("E"); // A, E, C, D, B В этом примере второй then добавляет микрозадачу, которая тоже выполняется до таймера. Если каждая микрозадача без конца создаёт следующую, очередь не опустеет. Браузер не доберётся до таймеров и отрисовки. Асинхронная запись кода сама по себе не гарантирует отзывчивость страницы. Конечную тяжёлую работу можно разбивать с передачей управления браузеру, а вычисления — выносить в Web Worker. Разбор очередей выполнения
556
18
Почему второй проход по итератору ничего не возвращает Массив хранит элементы. Итератор хранит состояние конкретного прохода
Почему второй проход по итератору ничего не возвращает Массив хранит элементы. Итератор хранит состояние конкретного прохода по ним. Если он уже дошёл до конца, новый цикл не вернёт его к началу. const values = [10, 20, 30]; const it = values[Symbol.iterator](); console.log([...it]); // [10, 20, 30] console.log([...it]); // [] console.log([...values]); // [10, 20, 30] Вызов next() продвигает итератор и возвращает объект с полями value и done. Когда done становится true, этот проход завершён. У массива можно запросить новый итератор. Но генератор обычно возвращает самого себя при запросе итератора: повторный for...of продолжит тот же проход. Поэтому перед двумя обработками данных проверьте, что у вас: коллекция, новый источник итераторов или один уже расходуемый итератор. Как устроен протокол обхода
590
19
Бинарный поиск: как одна граница зацикливает алгоритм Половину массива можно отбросить, только если он отсортирован. Но даже
Бинарный поиск: как одна граница зацикливает алгоритм Половину массива можно отбросить, только если он отсортирован. Но даже тогда нужно уменьшать диапазон после каждого несовпадения. def search(a, x): left, right = 0, len(a) - 1 while left <= right: mid = (left + right) // 2 if a[mid] == x: return mid if a[mid] < x: left = mid + 1 else: right = mid - 1 return -1 print(search([2, 5, 9], 8)) # -1 Здесь обе границы включены. Уже проверенный mid исключают через +1 или −1. Если оставить left = mid, диапазон из двух элементов может перестать сужаться. Проверьте пустой массив, один элемент, крайние позиции и отсутствующее значение. При дубликатах этот вариант возвращает найденный индекс, но не обязательно первый. Пошаговая трассировка
604
20
Почему NOT IN с NULL убирает все строки В SQL условие бывает не только истинным или ложным, но и неизвестным. Обычное сравнен
Почему NOT IN с NULL убирает все строки В SQL условие бывает не только истинным или ложным, но и неизвестным. Обычное сравнение с NULL даёт именно неизвестный результат. SELECT 3 AS id WHERE 3 NOT IN (1, NULL); -- Ни одной строки Выражение равносильно 3 <> 1 AND 3 <> NULL. Первая часть истинна, вторая неизвестна. Итог — неизвестно, а WHERE оставляет только строки с истинным условием. Если NULL попадёт в подзапрос для NOT IN, из результата могут исчезнуть все кандидаты. В зависимости от задачи можно исключить NULL внутри подзапроса или использовать связанный NOT EXISTS. Для проверки пропуска нужен IS NULL, а не = NULL. При этом поведение пустой строки зависит от СУБД: Oracle считает её NULL, PostgreSQL — отдельным значением. Примеры и таблица логики
626