Глава 3. Как найти ответ на загадку шута
Ролевка начинается. Направляйтесь в парк к королю. Спойте Джеду о подвигах Итана. Можете выбрать любой вариант.
Король даст задание найти три камня — аметист, сапфир и рубин. Алекс предлагает начать с главной улицы.
На пути вы попадете в засаду волка — предстоит бой. Победив его, не пропустите на земле рядом доллар — это вещь с эмоцией. Не забывайте также искать магические свитки на доступной территории — это сильно облегчит сражения.
Около бара стоит шут. Он загадает загадку, но вы пока не знаете ответ. Идите к бару. Вы заметите кровь и листок напоминания с остатками эмоции. Прочитайте ее и заходите в бар.
Вас встретит Даки в образе гнома. Прочитайте его эмоции. Алекс узнает, что он пьет в баре бесплатно. Намекните, что скажете об этот Джеду. Выберите все другие варианты вопросов, чтобы получить колокольчик от змей. Вам необходимо осмотреть бар и выяснить, что отпирает ключ, найденный у волка. Не пропустите эмоцию на клочке бумаги в зале с бильярдом. Также в этом зале будет ответ на загадку шута — в одной из записей на стене информация об истинных именах героев, ставших камнями.
За барной стойкой найдите шкатулку. Внутри лежит один из камней. Выходите из таверны и идите к шуту. Теперь вы знаете правильный ответ, поэтому выбирайте имена людей, а не названия камней. Шут даст монету, а также расскажет, что для подкупа тролля нужно 4 золотых. У вас уже должно быть три.
подзапросы lateral
В MySQL 8.0.14 добавлена поддержка зависимых подзапросов в части FROM, с помощью которых наша задача решается оптимальным образом. Сначала формируется список идентификаторов пользователей (производная таблица t1) и для каждого из выбираются нужные строки (коррелированный from-подзапрос t2).
select t2.* from (select user_id from posts group by user_id) as t1,
lateral (select * from posts where t1.user_id=posts.user_id order by date_added desc limit 3) as t2;
К удивлению, при выборе строк в подзапросе t2 сервер читает все строки группы и делает файловую сортировку вместо нахождения 3 нужных строк по уникальному индексу (user_id, date_added). Возможно в будущих версиях это поведение будет исправлено.
На сегодняшний день можно применить следующий трюк, благодаря которому MySQL будет использовать индекс — расширить выражение сортировки следующим образом:
.. order by user_id desc, date_added desc limit 3
Для выборки случайных строк из группы достаточно в lateral подзапросе заменить сортировку на случайную — order by rand().
Функция РАНГ() в MS EXCEL
Функция РАНГ(), английский вариант RANK(), возвращает ранг числа в списке чисел. Ранг числа — это его величина относительно других значений в списке. Например, в массиве {10;20;5} число 5 будет иметь ранг 1, т.
к. это наименьшее число, число 10 — ранг 2, а 20 — ранг 3 (это ранг по возрастанию, когда наименьшему значению присваивается ранг 1). Если список отсортировать, то ранг числа будет его позицией (если нет повторов).
- Синтаксис
- РАНГ(число>;ссылка>>
- Число — число, для которого определяется ранг.
Ссылка — ссылка на список чисел (диапазон ячеек с числами). Напрямую массив задать нельзя, формула =РАНГ(10;{10:50:30:40:50}) работать не будет. Но, если ввести формулу =РАНГ(B7;$A$7:$A$11), то она будет работать (хотя ячейка B7 — вне списка с числами). Если в B7 содержится число вне списка с числами, то формула вернет ошибку #Н/Д.
Нечисловые значения в ссылке игнорируются. Числам, сохраненным в текстовом формате, ранг также не присваивается, функция воспринимает их как текст.
Порядок — число, определяющее способ упорядочения.
- Если порядок равен 0 (нулю) или опущен, то MS EXCEL присваивает ранг=1 максимальному числу, меньшим значениям присваиваются большие ранги.
- Если порядок — любое ненулевое число, то то MS EXCEL присваивает ранг=1 минимальному числу, большим значениям присваиваются большие ранги.
Примечание: Начиная с MS EXCEL 2010 для вычисления ранга также используются функции РАНГ.СР() и РАНГ.РВ(). Последняя функция аналогична РАНГ().
Определяем ранг в списке без повторов
Если список чисел находится в диапазоне A7:A11, то формула =РАНГ(A7;$A$7:$A$11) определит ранг числа из ячейки А7 (см. файл примера).
Т.к. аргумент порядок опущен, то MS EXCEL присвоил ранг=1 максимальному числу (50), а максимальный ранг (5 = количеству значений в списке) — минимальному (10).
-
- Альтернативный вариант: =СЧЁТЕСЛИ($A$7:$A$11;»>»&A7)+1
- В столбце С приведена формула =РАНГ(A7;$A$7:$A$11;1) с рангом по возрастанию, ранг=1 присвоен минимальному числу. Альтернативный вариант: =СЧЁТЕСЛИ($A$7:$A$11;»»&B3)+1
- В столбце А содержатся названия группы, в столбце В — значения.
Связь функций НАИБОЛЬШИЙ()/НАИМЕНЬШИЙ() и РАНГ()
Функции НАИБОЛЬШИЙ() и РАНГ() являются взаимодополняющими в том смысле, что записав формулу =НАИБОЛЬШИЙ($A$7:$A$11;РАНГ(A7;$A$7:$A$11)) мы получим тот же исходный массив A7:A11.
Определяем ранг в списке с повторами
Если список содержит повторы, то повторяющимся значениям (выделено цветом) будет присвоен одинаковый ранг (максимальный, если использована функция РАНГ() или РАНГ.РВ()) или среднее значение, если РАНГ.СР()).
Наличие повторяющихся чисел влияет на ранги последующих чисел.
Например, если в списке целых чисел, отсортированных по возрастанию, дважды встречается число 10, имеющее ранг 5, число 11 будет иметь ранг 7 (ни одно из чисел не будет иметь ранга 6).
Иногда это не удобно и требуется, чтобы ранги не повторялись (например, при определении призовых мест, когда нельзя занимать нескольким людям одно место).
В этом нам поможет формула =РАНГ(A37;A$37:A$44)+СЧЁТЕСЛИ(A$37:A37;A37)-1
Предполагается, что исходный список с числами находится в диапазоне А37:А44.
Примечание. В MS EXCEL 2010 добавилась функция РАНГ.
РВ(число;ссылка;) Если несколько значений имеют одинаковый ранг, возвращается наивысший ранг этого набора значений (присваивает повторяющимся числам одинаковые значения ранга).
В файле примера дается пояснение работы этой функции. Также добавилась функция РАНГ.СР(число;ссылка;) Если несколько значений имеют одинаковый ранг, возвращается среднее.
Массив рангов
Для построения некоторых сложных формул массива может потребоваться массив рангов, т.е. тот же набор рангов, но в одной ячейке.
- Как видно из картинки выше, значения из диапазона В60:В67 и в ячейке D60 совпадают. Такой массив можно получить с помощью формулы =РАНГ(A60:A67;A60:A67) или с помощью формулы =СЧЁТЕСЛИ(A60:A67;»>»&A60:A67)+1
- Ранги по возрастанию можно получить с помощью формулы =РАНГ(A60:A67;A60:A67;1) или =СЧЁТЕСЛИ(A60:A67;»
Краткое описание mesh-объектов
Mesh-объект | Описание |
Plane (Плоскость) | Простейший двухмерный меш-объект. Его можно подразделить и, используя Режим пропорционального Редактирования, создать хорошую холмистую местность. |
Cube (Куб) | Основной 3D меш-объект. Хорошо подходит для конструирования прямоугольных моделей |
Circle (Окружность) | Не отображается как 3D объект пока не заполнен (fill), но его можно выдавливать (extrude) и изменять форму. |
UV Sphere (Сфера) | Сфера, сгенерированная из окружностей и сегментов. Похожа на глобус, состоящий из параллелей и меридианов. |
Ico Sphere (Сфера) | Сфера, сформированная из треугольников. Похожа на здание Epcot |
Cylinder (Цилиндр) | Похож на бочку, закрытую с обеих сторон. Если убрать оба конца —получится труба. |
Cone (Конус). | Основная закрытая коническая форма |
Torus Тор | Меш в форме бублика |
Monkey (Обезьянка). | Забавный меш-объект по имени Сюзанна (Suzanne), который один из разработчиков программы, Виллем-Пол ван Овербрюгер (Willem-Paul van Overbruggen (SLiD3)), решил добавить в список меш-объектов. |
Порядок обхода
Когда мы задаем некоторый набор вершин треугольника, то вместе с этим определяем и порядок их расположения, зависящий от того, каким образом будет производиться обход вершин треугольника при передвижении от одной вершины к другой: по часовой стрелке (англ. «clockwise») или против часовой стрелки (англ. «counter-clockwise»). Каждый треугольник состоит из 3 вершин, и мы указываем данные вершины в том порядке, в котором будет происходить их обход:
На этом рисунке вы можете видеть, что мы начинаем обход с вершины №1, а дальше должны выбрать, будет ли следующей вершиной вершина №2 или же это будет вершина №3. Данный выбор задает порядок обхода рассматриваемого треугольника. Посмотрите на следующий код:
float vertices[] = {
// По часовой стрелке
vertices, // вершина 1
vertices, // вершина 2
vertices, // вершина 3
// Против часовой стрелки
vertices, // вершина 1
vertices, // вершина 3
vertices // вершина 2
};
1 |
floatvertices={ // По часовой стрелке vertices,// вершина 1 vertices1,// вершина 2 vertices2,// вершина 3 // Против часовой стрелки vertices,// вершина 1 vertices2,// вершина 3 vertices1// вершина 2 }; |
Каждый набор из 3 вершин, образующих треугольник (напомню, треугольник — это один из объектов-примитивов в OpenGL), задает и порядок его обхода. При рендеринге примитивов OpenGL использует эту информацию, чтобы определить, с каким треугольником он имеет дело: обращенным лицевой стороной или же тыльной. Треугольники, заданные вершинами с обходом против часовой стрелки, по умолчанию обрабатываются как обращенные к зрителю лицевой стороной.
Когда вы определяете порядок своих вершин, то представляете соответствующий треугольник так, как если бы он был повернут к вам лицевой стороной, поэтому с точки зрения наблюдателя у такого треугольника порядок обхода его вершин будет соответствовать движению против часовой стрелки. Плюсом данного способа указания всех вершин является то, что фактический порядок обхода вычисляется на этапе растеризации, то есть когда уже запущен. Тогда вершины просматриваются с позиции наблюдателя.
Все вершины треугольника, которые затем предстают перед наблюдателем, действительно имеют правильный порядок обхода, как мы и указывали, но вершины треугольников на другой стороне куба теперь отображаются таким образом, что их порядок обхода становится обратным. В результате некоторые из треугольников, которые мы наблюдаем, воспринимаются обращенными к нам лицевой стороной, а другие — тыльной. Этот эффект показан на следующем рисунке:
С помощью вершинных данных мы определили 2 треугольника так, что порядок их обхода соответствует движению против часовой стрелки (для обоих треугольников — вершина 1, вершина 2, вершина 3). Однако с текущей позиции наблюдателя дальний треугольник имеет порядок обхода вершин по часовой стрелке: вершина 1, вершина 2 и вершина 3. Несмотря на то, что мы задавали его с порядком обхода против часовой стрелки, теперь он отображается с порядком по часовой стрелке. Это именно те непросматриваемые грани, которые мы хотим отсечь!
Глава 1. Как читать эмоции на вещах и зачем это нужно
Поговорите с братом
Ваши ответы тут не играют важной роли. Гейб поставит новую пластинку и начнет танцевать
К нему можно присоединиться или остаться в стороне.
Можете изучить квартиру. Ваша задача — разобрать вещи. Кроме того, есть возможность прочитать сообщения на телефоне. На столе лежит письмо. Над ним будет пульсировать уже знакомый кружок. Это означает, что на предмете остался обрывок чужой эмоции, которую можно почувствовать. Такие предметы дадут чуть больше информации о знакомых Алекс, а также призы, поэтому смотрите по сторонам. В прихожей можно заметить трещину в стене — на ней тоже осталась эмоция.
1.10.7. Математическая постановка
Данные обучающие векторы $x_i \in R^n$, i = 1,…, l и вектор-метка $y \in R^l$ дерево решений рекурсивно разбивает пространство признаков таким образом, что образцы с одинаковыми метками или аналогичными целевыми значениями группируются вместе.
Пусть данные в узле m быть представлен $Q_m$ с участием $N_m$ образцы. Для каждого раскола кандидатов $\theta = (j, t_m)$ состоящий из функции $j$ и порог $t_m$, разделите данные на $Q_m^{left}(\theta)$ а также $Q_m^{right}(\theta)$ подмножества$$Q_m^{left}(\theta) = {(x, y) | x_j <= t_m}$$$$Q_m^{right}(\theta) = Q_m \setminus Q_m^{left}(\theta)$$
Качество кандидата разделения узла $m$ затем вычисляется с использованием функции примеси или функции потерь $H()$, выбор которых зависит от решаемой задачи (классификация или регрессия)$$G(Q_m, \theta) = \frac{N_m^{left}}{N_m} H(Q_m^{left}(\theta)) + \frac{N_m^{right}}{N_m} H(Q_m^{right}(\theta))$$
Выберите параметры, которые минимизируют примеси$$\theta^* = \operatorname{argmin}_\theta G(Q_m, \theta)$$
Рекурсия для подмножеств $Q_m^{left}(\theta^*)$ а также $Q_m^{right}(\theta^*)$ пока не будет достигнута максимально допустимая глубина, $N_m < \min_{samples}$ или же $N_m = 1$.
1.10.7.1. Критерии классификации
Если целью является результат классификации, принимающий значения 0,1,…, K-1, для узла m, позволять$$p_{mk} = 1/ N_m \sum_{y \in Q_m} I(y = k)$$
быть пропорцией наблюдений класса k в узле m. Еслиmявляется конечным узлом, для этого региона установлено значение $p_{mk}$. Общие меры примеси следующие.
Джини:$$H(Q_m) = \sum_k p_{mk} (1 — p_{mk})$$
Энтропия:$$H(Q_m) = — \sum_k p_{mk} \log(p_{mk})$$
Неверная классификация:$$H(Q_m) = 1 — \max(p_{mk})$$
1.10.7.2. Критерии регрессии
Если целью является непрерывное значение, то для узла m, общими критериями, которые необходимо минимизировать для определения местоположений будущих разделений, являются среднеквадратичная ошибка (ошибка MSE или L2), отклонение Пуассона, а также средняя абсолютная ошибка (ошибка MAE или L1). MSE и отклонение Пуассона устанавливают прогнозируемое значение терминальных узлов равным изученному среднему значению $\bar{y}_m$ узла, тогда как MAE устанавливает прогнозируемое значение терминальных узлов равным медиане $median(y)_m$.
Среднеквадратичная ошибка:$$\bar{y}m = \frac{1}{N_m} \sum{y \in Q_m} y$$$$H(Q_m) = \frac{1}{N_m} \sum_{y \in Q_m} (y — \bar{y}_m)^2$$
Половинное отклонение Пуассона:$$H(Q_m) = \frac{1}{N_m} \sum_{y \in Q_m} (y \log\frac{y}{\bar{y}_m} — y + \bar{y}_m)$$
Настройка может быть хорошим выбором, если ваша цель — счетчик или частота (количество на какую-то единицу). В любом случае, y>=0 является необходимым условием для использования этого критерия. Обратите внимание, что он подходит намного медленнее, чем критерий MSE. Средняя абсолютная ошибка:$$median(y)m = \underset{y \in Q_m}{\mathrm{median}}(y)$$$$H(Q_m) = \frac{1}{N_m} \sum{y \in Q_m} |y — median(y)_m|$$
Средняя абсолютная ошибка:$$median(y)m = \underset{y \in Q_m}{\mathrm{median}}(y)$$$$H(Q_m) = \frac{1}{N_m} \sum{y \in Q_m} |y — median(y)_m|$$
Обратите внимание, что он подходит намного медленнее, чем критерий MSE
Глава 1. Как извиниться перед Гейбом
Скажите Джеду, что работа завершена, вернется Гейб. Он хочет поговорить с Алекс на крыше. В процессе диалога с братом, Алекс поймет, что он на нее не злится, после чего у вас будет выбор — рассказать ему о способностях или о прошлом. Гейб отдаст Алекс свой коробок с последней спичкой. Неожиданно появится Райан и скажет, что Итан пропал.
Алекс понимает, что в этом есть и ее вина, однако Гейб решает отложить этот разговор на потом. Компания отправляется искать ребенка. Ситуация осложняется запланированным взрывом в шахте. Гейб звонит в офис «Тайфон» и договаривается, чтобы технические работы отложили.
Выделение подобъектов расположенных в ряд
Допустим, что необходимо выделить ряд вершин, ребер или граней расположенных на одной прямой. Это осуществляется при помощи зажатой клавиши «Alt» и щелчком правой кнопки мыши между вершинами данной прямой (для вершин) или указанием ребра, лежащего на этой прямой (для ребер). Аналогично выделяется и ряд граней.
Если вместе с «Alt» зажать «Shift», то можно выделить сразу несколько рядов подобъектов, расположенных на разных прямых.
Выделение ряда параллельных ребер производится правой кнопкой мыши при зажатых клавишах «Alt+Ctrl», а нескольких рядов – при зажатых клавишах «Alt+Ctrl+Shift».
Здесь следует сделать одно важное замечание. Для корректного выделения ряда подобъектов, необходимо, чтобы на прямой были только вершины с четырьмя ребрами
Ели же в каком-то месте их будет больше или меньше, то выделение ряда там будет прервано.
Добавление объектов в Blender
Самым простым способом что-либо добавить в Blender’е – нажать на кнопку “Add” в левой верхней части окна предпросмотра, выбрать тип добавляемого объекта и сам объект.
Альтернативой может быть нажатие горячей клавиши Shift+A, которая выдаст то же самое меню:
Все объекты всегда появляются на месте 3D курсора. О других не менее важных его функциях можно почитать в материале про выбор и изменение объектов.
Помимо примитивных фигур в списке мешей есть некая Monkey. Это обезьяна, и её зовут Сюзанна. Она, так сказать, маскот Blender’а, его визитная карточка.
На практике Сюзанну можно использовать при тестировании материалов, текстур, анимаций и освещения.
пользовательские переменные
Та же идея, что и в предыдущем варианте, только реализована с помощью пользовательских переменных (user variables). Актуально для версий, в которых нет оконных функций.
select post_id, user_id, date_added, post_text from(select posts.*, if(@gr=user_id, @i:=@i+1, @i:=1 + least(@gr:=user_id,)) xfrom posts, (select @i:=, @gr:=) t order by user_id, date_added desc) t1 where x <=3;
Как и в примере с row_number(), мы нумеруем сообщения каждого пользователя в порядке убывания даты добавления (только делаем это с помощью пользовательских переменных), затем оставляем только те строки, у которых № меньше или равен 3.
Способ можно применять и для выборки нескольких случайных сообщений юзера. Однако простая замена сортировки по убыванию даты на случайную не даст нужного эффекта.
select post_id, user_id, date_added, post_text from(select t2.*, if(@gr=user_id, @i:=@i+1, @i:=1 + least(@gr:=user_id,)) xfrom (select posts.*, rand() q, @z:=1 from posts) t2, (select @i:=, @gr:=) t order by user_id, q) t1 where x <=3
Обратите внимание на добавление ещё одной переменной @z:=1, которая более нигде не применяется. С некоторых пор оптимизатор научился упрощать тривиальные с его точки зрения from-подзапросы, перенося условия из них во внешний запрос
Однако, если в подзапросе используются переменные, то пока оптимизатор материализует такие подзапросы.
В общем, пользовательские переменные — мощный инструмент написания и оптимизации запросов, но нужно быть очень внимательными при работе с ними, понимать на каком эффекте основан, используемый вами трюк, и проверять работоспособность в новых версиях. Подробнее см Оптимизация запросов MySQL с использованием пользовательских переменных
Глава 5. Как выбраться из подсознания
Вы оказываетесь вместе с Гейбом в больнице. Неожиданно появляется отец, который просит Алекс зайти к матери.
Изучите мамины ключи и эмоцию на них. Мать находится за шторой. После разговора с ней появится Гейб, который скажет, что все было не совсем так
Снова оказавшись в палате, обратите внимание на стакан воды. Разговор с матерью начнется также, как и в первый раз, но когда она начнет кашлять, принесите воды
Мать подарит Алекс медальон и попросит следить за отцом и братом.
Теперь вы дома у Алекс. После разговора с Гейбом включайте проигрыватель. Смотрите кат-сцену ссоры отца с сыном. Время снова отматывается на начало. Изучая дом, не пропустите на кухне визитку с эмоцией. В ходе новой кат-сцены узнаем, как отец бросил своих детей.
Мы в приюте
Снова изучите доступные предметы, обратите внимание — на одной из кроватей струны для гитары с эмоцией. Подойдите к сундуку с вещами в конце комнаты
Вы увидите разных приемных родителей в окнах, читайте их эмоции.
После очередного диалога с Гейбом Алекс приходит в себя в реальном мире. Чтобы выбраться, нужен свет, поэтому девушка использует спичку, которую ей подарил брат, чтобы зажечь фонарь.
У вас только один путь — вперед. В итоге фонарь погаснет, однако Алекс заметит сильное красное свечение в темноте — ауру злости.
Ручное выделение множества подобъектов
Как было отмечено выше, если необходимо выделить несколько объектов или подобъектов, то это можно сделать при зажатой клавише «Shift». Этот способ выделения подходит для малого числа объектов/подобъектов. Если же необходимо выделить множество объектов/подобъектов, то для этой цели в Blender предназначены специальные инструменты. Рассмотрим их.
Выделение прямоугольной рамкой
Включение инструмента «Рамка» осуществляется нажатием клавиши «B», а выделение производится зажатой левой кнопкой мыши. Данный инструмент предназначен, в основном, для выделения однотипных подобъектов расположенных на прямых линиях по вертикали или горизонтали.
Для выделения нескольких групп подобъектов подряд, например, сначала вертикальных, а затем горизонтальных, клавишу «Ctrl» зажимать не нужно, достаточно, при уже выделенных подобъектах, снова нажать клавишу «B».
Отключается рамка нажатием клавиши «Esc» или правой кнопкой мыши.
Так же рамкой можно снимать выделение, для этого нужно нажать «B», но вместо левой кнопки мыши нажать на её колёсо.
Выделение окружностью
Включение инструмента «Окружность» осуществляется нажатием клавиши «С», а выделение зажатой левой кнопкой мыши. Инструмент «Окружность» предназначен, в основном, для выделения подобъектов или их групп, имеющих круглую форму. Размер окружности регулируется колесом мыши. Отключается данный инструмент нажатием на клавишу «Esc», «Enter» или правую кнопку мыши.
Снятие выделений с подобъектов данным инструментом происходит путем нажатия на колесо мыши.
Выделение произвольной формой
Если же необходимо выделить группы подобъектов сложной формы расположенных хаотично, то для этого предназначен инструмент «Лассо». Выделение им происходит левой кнопкой мыши при зажатой клавише «Ctrl».
Снимается выделение данным инструментом так же левой кнопкой мыши, но при зажатых клавишах «Ctrl+Shift».
Рассмотренными способами можно выделять как объекты, так и подобъекты во всех режимах отображения.
Заключение
Сводная таблица, показывающая среднее время выполнения изложенных выше способов для нахождения трёх последних и трёх случайных сообщений каждого пользователя на тестовых данных в 16000 строк, равномерно распределенных среди count(distinct user_id) = 20.
время, с | ||
3 последних | 3 случайных | |
1. зависимый подзапрос | 10.8 | — |
2. join + group by | 11 | — |
3. group_concat() | 0.06 | 0.03 |
3. модифицированный вариант + WITH | 0.03 | 0.016 |
3. модифицированный вариант без WITH | 0.08 | — |
4. row_number() | 0.15 | 0.17 |
5. пользовательские переменные | 0.13 | 0.14 |
6. LATERAL | 0.005 | 0.03 |
Если ваша СУБД поддерживает подзапросы lateral, то используйте их. Вообще, каждый раз, когда есть необходимость «для каждого значения выбрать …» — возможно вы сможете эффективно решить задачу, используя LATERAL производные таблицы. Подробнее об этой функциональности можно прочитать в статье В MySQL 8.0.14 добавлена поддержка производных таблиц типа LATERAL.
Неожиданно высокую эффективность показал третий способ, особенно для выборки случайных строк из группы. Неожиданно, потому что как правило рекомендуют использовать второй и четвертый (для MySQL до недавнего времени его реализацию через переменные, т.е. пятый) способы.
Также не забывайте про вариант реализации lateral во внешнем приложении: сначала выбираем список идентификаторов групп, потом в цикле отдельными запросами находим нужные строки для каждой группы. Порой встречается ошибочное мнение, что это ламерский подход и правильно решать задачу в один запрос к базе. По эффективности множество «простых» запросов, выбирающих по индексу нужные строки, лучше одного «сложного», который многократно сканирует всю таблицу. Разумеется это справедливо, когда в группах много элементов, и нужно вернуть лишь малую часть, иначе накладные расходы могут превысить выигрыш от снижения количества прочитанных строк.
P.S.При выборе подходящего варианта проводите тестирование в своем окружении.
Если после прочтения статьи ваш вопрос остался нерешенным, задавайте его на форуме SQLinfo.
Все права на данную статью принадлежат порталу SQLInfo.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в бумажных изданиях допускается только с разрешения редакции.