РезультатВыборки = Новый Массив;
ПервоначальнаяТаблица = Новый ТаблицаЗначений;
ПервоначальнаяТаблица.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для СчЭлементов = 1 По 2 * НадоСлЭлементов Цикл
Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
ПервоначальнаяТаблица.Добавить().Товар = Номенклатура;
КонецЦикла;
Запросо = Новый Запрос;
Запросо.Текст = "ВЫБРАТЬ
| НедействительныеСсылки.Товар КАК Товар
|ПОМЕСТИТЬ Товары
|ИЗ
| &НедействительныеСсылки КАК НедействительныеСсылки
|
|ИНДЕКСИРОВАТЬ ПО
| Товар
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| МАКСИМУМ(ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка)) КАК Номенклатура,
| НедействительныеСсылки.Товар
|ПОМЕСТИТЬ ВсякаБяка
|ИЗ
| Товары КАК НедействительныеСсылки
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
| ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
| ПО (ИСТИНА)
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО НедействительныеСсылки.Товар >= Номенклатура.Ссылка
| И (Номенклатура.ЭтоГруппа = ЛОЖЬ)
|
|СГРУППИРОВАТЬ ПО
| НедействительныеСсылки.Товар
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ " + Формат(НадоСлЭлементов, "ЧГ=") + "
| ВсякаБяка.Номенклатура
|ИЗ
| ВсякаБяка КАК ВсякаБяка";
Запросо.УстановитьПараметр("НедействительныеСсылки",ПервоначальнаяТаблица);
//Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
РезЗапроса = Запросо.Выполнить();
Если Не РезЗапроса.Пустой() Тогда
СлучайныеТовары.ЗагрузитьЗначения(РезЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура"));
СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
КонецЕсли;
Сообщить(СлучайныеТовары.Количество());
(2) sssss_aaaaa_2011, наверняка автор имеет в виду получение с помощью ГенераторСлучайныхЧисел: пронумеровать все элементы справочника от 1 до КоличествоЭлементов, получить нужное количество случайных номеров в диапазоне от 1 до КоличествоЭлементов, получить нужные элементы по этим случайным номерам.
(4) Lovish, нумерация элементов - очень трудоемкий этап. Трудоемкость растет квадратично по отношению к числу элементов справочника. Попробуйте для примера пронумеровать в запросе свой справочник номенклатуры или контрагентов - результата придется ждать очень долго.
ничем не плох, просто организатор обсуждения про один способ знает и просил что-нибудь аналогичное.
Думаю первый способ как раз и был: ГенераторСлучайныхЧисел
в самом запросе случаное не получить, в любом случае, случайные числа нужно получать отдельно и передавать в запрос в виде параметров или в виде таблицы значений с числами. а там уже у кого как фантазия работает.
(17) spezc, ну почему же - можно. Топикстартер стартанул таким тоном, что раскалываться не хотелось, но, видимо, что-то озвучить придётся :(
ГенераторСлучайныхЧисел не на волшебной пыльце работает, это обычные вычисления, которые можно проделать в запросе. Классический ГСЧ (дальше могу слегка напутать - последний раз занимался этим вопросом ещё в прошлом веке) это два нечётных (чтобы не накапливались нули в младших разрядах, что приведёт к вырождению ГСЧ) числа - seed и как_там_его_называют. Каждое обращение к ГСЧ происходит следующее:
(17) spezc, ты статьи ildarovich по запросам читал же? По-моему, он запросами скоро задачи из курса высшей математики начнет решать, к этому все идет :) Хотя... Эммм... Он уже их решает вроде...
(17) spezc, тут я и хотел разнообразные фантазии увидеть. Даже если ввести таблицу случайных чисел или случайный параметр - что дальше со справочником делать? Тут уже предложили через "подобно" отбирать, но тогда некоторые коды могут иметь преимущество при выборе. А хотелось бы бОльшей случайности.
А возможно, кто-то и источник энтропии в запросе подскажет где взять. Если работа многопользовательская, то можно время последнего записанного документа использовать, но это крайне не надежно.
А возможно, кто-то и источник энтропии в запросе подскажет где взять
А просто передать в параметр значение одинэсовского ГСЧ чем плохо? Запрос всё-равно не в отдельной вселенной выполняется, туда по-любому можно параметр передать.
а если просто запрос типа "выбрать первые N ссылка из справочник.мойсправочник упорядочить по " а тут уже сортировку и направление случайным образом выбирать
(25) Ну если очень хочется, то прямой запрос в руки. Сам часто использую для объединения стороннх данных и регистра сведений через Merge. А там миллионы записей.
(26) Cool_vsi, а что, формально всё соблюдено. Как говорил Дядя Фёдор коту Матроскину: "Чтобы выбрать в запросе что-то случайное, надо сначала передать туда что-то случайное, а у нас в запросе ГСЧ нет".
(26) Cool_vsi, это будет работать, но все же это не метод "в запросе".
Кроме того, если уж выбрали весь справочник в память, нужно сразу выбирать из него элементы генерацией пяти случайных чисел (проверив, что они различные). Это будет гораздо быстрее, чем для каждой строки получить случайное число (а если строк 10 тысяч?), а затем эту огромную таблицу перегонять в запрос.
Тут как раз и видна проблема: для того, чтобы выбрать всего пять элементов, приходится выбирать все элементы справочника.
(30) ildarovich, я сам удивился но работает быстро, меньше секунды для 7000 элементов, формально исходя из название темы все условия соблюдены ..а реально да , это не 1 запрос..насчет выборки всех элементов, думаю если в запросе сделать несколько виртуальных таблиц,в которых будут все элементы то по скорости будет не намного быстрее...да сам хочу посмотреть на чистый запрос в 1с, который быстро случайно выберет n элементов...
все что можно написать из 1С (по моему мнению) - это проиндексировать выборку случайными значениями и потом выбрать N элементов с учетом сортировки - способ затратный получается.
Проще сделать прямой запрос к базе и получить в зависимости от вида SQL (NEWID()), Рostgree (Random()), db2(не помню, но тоже что то c RAND()) набор ID - в случае файловой остается чистый 1с например - выборка.Следующий и ГСЧ.
не универсально конечно.. но и ресурсы не резиновые - создания таблиц порождающими запросами да если еще и не в один поток - быстро загонит бд в ступор
(31) poyson, а что с этим числом дальше делать? Ведь задача: выбрать случайные элементы из справочника в запросе. Как для этого случайное число дальше использовать? Нужен текст запроса наподобие (11).
(36) minimajack, я так понимаю что при сид=постоянное значению(попробовал разные варианты сид при одинаковых вариантах сид рез одинаков), то и выводиться будут тоже самое. Вариант 11 такойже только лаконичнее. Рандом число все-равно передается в запрос, и все пляшет от него.
(38) minimajack, общий принцип одинаковый, передаем случайное число получаем случайное, вариантов на самом деле очень много если передавать случайное число...я думаю всем интересен запрос, который сам будет генерировать случайный элементы без передачи в него случайных чисел, ваш вариант интересен с математической точки зрения...но с точки зрения скорости работы и принципа если есть вариант проще не стоит загоняться, ваш вариант проигрывает другим вариантом с прицыпом передачи в запрос случайного числа...
(36) minimajack, хороший вариант. Его еще можно улучшить, если код-число преобразовывать по-другому. По формуле (А * Код + B) % 2^32, где A, B - некоторые "большие числа". Примеры "хороших" чисел можно посмотреть у Кнута. Например, А = 1664525, B = 0.
Если не передавать в запрос случайные значения, то можно только ориентироваться на какие-то изменения в базе. Например, как писалось выше на время создания, версию данных последнего документа или на количество каких-то записей. Но если с данными ничего не происходит, то вариантов нет.
(39) hibico, вообще говоря, можно создать небольшую временную таблицу, где хранить номер итерации, увеличивая его при каждой следующей случайной выборке.
Но, конечно, хочется чего-либо типа времени, объема свободной памяти, всего, что может быть настоящим источником энтропии. ...блокировки?...
(43) ildarovich, в доступных функциях запроса ничего не доступно, так что хоть тысячу раз запускай - ничего не изменится и во временных таблицах...причина этому - детерминированность алгоритмов - фактически это закон для компьютера. У нас не квантовые компьютеры - так что без внешнего источника энтропии - рыпаться бесполезно.
Если есть возможность сгенерировать до запроса, есть МенеджерКриптографии - там и парится не надо.
ВЫБРАТЬ
Контрагенты.Ссылка КАК Ссылка,
Контрагенты.Код КАК Код,
КОЛИЧЕСТВО(Контрагенты.Код) * 0 КАК Индекс
ПОМЕСТИТЬ ВТ_ДАННЫЕ
ИЗ
Справочник.Контрагенты КАК Контрагенты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты1
ПО Контрагенты.Ссылка >= Контрагенты1.Ссылка
СГРУППИРОВАТЬ ПО
Контрагенты.Ссылка,
Контрагенты.Код
ИНДЕКСИРОВАТЬ ПО
Индекс
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ ПЕРВЫЕ 5
ВТ_ДАННЫЕ.Ссылка,
ВТ_ДАННЫЕ.Код,
ВТ_ДАННЫЕ.Индекс
ИЗ
ВТ_ДАННЫЕ КАК ВТ_ДАННЫЕ
УПОРЯДОЧИТЬ ПО
ВТ_ДАННЫЕ.Индекс
Показать
Нашел!!! =))
Индексирование наше все )) для скульной базы работает
(46) Ёпрст, проверил?
(47) как раз именно вариант с подзапросом с индексированием виртуального нуля дает случайную выборку
зы индексировать не обязательно =)
что бы не смущало
(55) С фигали выполнено, если не воспроизводится ?
И.. в (0) нет ни слова об использованиии СУБД.. для скуля, вообще проще rand() использовать и привет.
(56) Ёпрст, согласен не всегда воспроизводится, на базе с > 5000 записей работает, на маленькой выборке результат один и тот же...жаль, видимо остается в кэше...
Ну если передавать через параметр случайное число нельзя, тогда можно создать какой-то объект (или использовать существующий), например регистр сведений, и с какой-нибудь периодичностью заполнять его новым случайным числом (числами). А в запросе выбирать данный объект и на его основе делать выборку элементов.
варианты привязки к коду номера элемента как к цифрам бред, не везде в коде есть цифры, или например еше есть буквы, или только буквы...пока считаю лучшим вариантом мой...абсолютный рандом =)
(68) Cool_vsi, метод, приведенный в (26) слабо соответствует условиям задачи. Главное в условии - сделать выбор "в запросе". У вас же основные действия, а именно, добавление колонки со случайными числами, производятся вне запроса.
То есть последовательность у вас такова:
1) выбираем ВЕСЬ справочник в таблицу значений;
2) добавляем колонку и записываем в каждый элемент новой колонки случайное число;
3) возвращаем ВЕСЬ справочник с добавленной колонкой в запрос;
4) сортируем по рандомному столбцу;
5) отбираем первые 5.
Если убрать из вашего алгоритма явно избыточные (абсолютно лишние) действия, то должен остаться алгоритм:
1) выбираем ВЕСЬ справочник в таблицу значений;
2) выбираем с помощью ГСЧ из таблицы значений 5 разных элементов;
3) возвращаем выбранные случайные элементы в запрос.
то станет очевидным, где на самом деле делается случайный выбор.
Вот, например, в статье "Порождающий запрос" есть запрос, формирующий временную таблицу псевдослучайных чисел прямо в запросе. То есть проблемы получения таблицы псевдослучайных чисел в запросе нет. Проблема в том, чтобы соединить ее с таблицей справочника, не выводя их из запроса. Вы этот вопрос обошли, нарушив (по моему мнению) условия задачи.
С другой стороны, предложенный в (26) метод (с учетом поправок) очевиден и для практики совершенно нормален (единственно возможен?), если не задано условие "в запросе".
(69) ildarovich, я не спорю что мой вариант не совсем подходит под условия задачи. Но варианты с передачей в запрос случайного числа и привязке к коду еще большее не подходят на мой взгляд.Самому интересно решение данного вопроса
(71) (75) caponid, совершенно лишняя нумерация справочника в запросе. Это тяжелая операция, которая требует соединения справочника с собой. Если разрешить себе выбор вне запроса (что не соответствует условию), то лучше делать так
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, 0 КАК Отбор ИЗ Справочник.Номенклатура ГДЕ НЕ ЭтоГруппа");
ВсеСсылки = Запрос.Выполнить().Выгрузить();
ГСЧ = Новый ГенераторСлучайныхЧисел();
Пока ВсеСсылки.Итог("Отбор") < 5 Цикл
ВсеСсылки[ГСЧ.СлучайноеЧисло(0, ВсеСсылки.Количество() - 1)].Отбор = 1
КонецЦикла;
Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&ОтборныеСсылки)");
Запрос.УстановитьПараметр("ОтборныеСсылки", ВсеСсылки.Скопировать(Новый Структура("Отбор", 1)));
Запрос.Выполнить().Выгрузить().ВыбратьСтроку("Случайные элементы:")
Показать
Конечно, в практическом применении нужно учесть, что справочник может содержать менее 5 элементов и проверять зацикливание, ну и обеспечить выбор пяти РАЗЛИЧНЫХ ссылок вообще не через долгий подсчет, а через соответствие.
(81) ildarovich,
"тяжелая операция соединения справочника с собой" - может быть и не так тяжела как выгрузка справочника в ТЗ. Надо сравнить в профайлере хотябы для SQL.
Какие вообще есть варианты?
В общем случае внутри запроса 1С получить случайное число невозможно (в частном случае, есть разные варианты – например, считать количество каких-либо постоянно добавляемых элементов справочника или смотреть какой-то объект в базе, куда мы постоянно специально будем записывать случайное число).
Следовательно, при выполнении запроса придётся каждый раз передавать случайное число (назову его Rand), т.е. при инициализации запроса одним и тем же случайным числом мы получим одни и те же "случайные" данные.
Итак, мы передали в запрос случайное число, что дальше?
Чтобы решение было универсальным мы можем привязаться только к стандартным реквизитам (других в справочнике просто может и не быть).
Из стандартных реквизитов подходит нам всего два - это уникальный "код" и относительно случайное "наименование". (С "ссылкой" мы никаких операций в запросе не сможем провести, поэтому она не подходит. Остальные реквизиты не обеспечивают практически никакой случайности, хотя если добавить и их, то случайность как минимум не понизится, но это замедлит процесс вычисления.)
Какой бы путь мы не выбрали нам всё равно придётся генерировать некий ключ на основе реквизитов "код" и "наименование" (в документах была бы ещё и "дата"). И ключ этот должен быть числовой, чтобы далее взаимодействовать с Rand.
Алгоритм вычисления ключа: Допустим и "наименование" и "код" имеют тип "строка". Чтобы обеспечить перевод строк в числа, нам понадобится временная таблица кодировки символов (с полями "Символ" и "Число") и функция "ПОДСТРОКА". Таким образом, выбирая символ, мы сразу сопоставляем ему число. Ну а далее из этих чисел по какой-нибудь хитрой формуле считаем ключ. Например, перемножаем все числа между собой (что-то у меня фантазия ещё не разогрелась).
Имея у каждого элемента справочника уникальный числовой ключ и случайное число, которым мы инициализировали запрос, выбрать случайные несколько элементов уже проще. Например, считаем поле «Порядок» как остаток от деления «ключа» на «Rand» (с помощью функции «Выразить»). Далее упорядочиваем по полю «Порядок» и выбираем первые N.
(72) Патриот, все логично, примерно так у меня и сделано. Я, в общем-то, задал вопрос для проверки: не пропустил ли я какой-либо более простой вариант решения этой задачи или нет ли какой свежей идеи. Ссылку на свое решение специально не привел, чтобы не затормозить приток идей.
Для меня обсуждение оказалось полезным по нескольким причинам:
- в комментарии (11) предложена свежая идея использование оператора "ПОДОБНО". Если бы можно обеспечить "ортогональность" сравнения через "ПОДОБНО" кодов справочника с несколькими базисными строками (чтобы результат сравнения делил справочник примерно пополам и для каждой базисной строки деление было бы независимым), то можно было бы развить этот подход;
- в комментарии (23) приведена полезная ссылка, которая напомнила, как можно ускорить решение, сократив затраты на сортировку. В результате смог еще ускорить свое решение;
- в комментарии (45) приведена одна из возможностей нахождения источника энтропии в запросе (правда, не надежная) и остается небольшая надежда, что, вдруг, есть и другие.
Давно наблюдаю за темой.. прочитал последний топик, где вопрос возникает как взять некое число рандом..
А если рассмотреть в запросе РазностьДат? Т.е. Некая константа.. Дата регистрации организации и текущая дата.
(73) anterehin,
1. отнимая от текущей даты константу случайность не повысится, т.е. легче просто взять текущую дату.
2. текущую дату надо в запрос передать, т.к. внутри её не вычислить.
3. "Дата регистрации организации" скорее всего есть не в каждой базе, т.е. это ограничивает универсальность
Запрос = Новый Запрос;
Запрос.Текст = "Выбрать Спр.Ссылка ИЗ Справочник.Контрагенты ГДЕ ..."; // Условие не пишу. Любое, которое нужно
Выборка = Запрос.Выполнить.Выбрать();
МассивСлучайныхЧисел = ПолучитьМассивСлучайныхЧисел();
// Функция "ПолучитьМассивСлучайныхЧисел()" должна возвращать массив случайных чисел
// от 0 (включая) до 1 (не включая) в нужном для задачи количестве.
// Как сгенерировать случайное число - обсуждать не хочу, в этой ветке предложено много хороших вариантов,
// кроме того в интернете очень много алгоритмов на эту тему.
Для каждого СлучайноеЧисло из МассивСлучайныхЧисел Цикл
СлучайнаяСсылка = Выборка.Получить( Цел( СлучайноеЧисло * Выборка.Количество() ) );
Сообщить( Строка( СлучайнаяСсылка ) );
КонецЦикла;
Показать
В результате всё решается в один запрос, без промежуточных таблиц и без анализа значений реквизитов справочника (в конце концов, разработчик может установить для кода или для наименования нулевую длину, и тогда просто нечего будет анализировать).
РезультатВыборки = Новый Массив;
Для СчЭлементов = 1 По НадоСлЭлементов Цикл
Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
Запросо = Новый Запрос;
Запросо.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
| ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка) КАК Номенклатура
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
| ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
| ПО (ИСТИНА)
|ГДЕ
| Номенклатура.Ссылка >= &Ссылка
| И НЕ Номенклатура.Ссылка В (&Массиво)
| И Номенклатура.ЭтоГруппа = ЛОЖЬ";
Запросо.УстановитьПараметр("Ссылка", Номенклатура);
Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
РезЗапроса = Запросо.Выполнить();
Если Не РезЗапроса.Пустой() Тогда
Номенклатура = РезЗапроса.Выгрузить()[0].Номенклатура;
РезультатВыборки.Добавить(Номенклатура);
КонецЕсли;
КонецЦикла;
СлучайныеТовары.ЗагрузитьЗначения(РезультатВыборки);
СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
Показать
Кажется, что первый элемент будет часто попадаться - но это лишь дыра в воображении. И тесты и разброс GUID-ов показывают, что все очень равномерно. Могут возникнуть трудности с количеством элементов сравнимым с мощностью справочника (быстродействие) - серия последовательных запросов ведет себя медленнее одного запроса сразу с таблицей внутри,
который можно сделать следуя данной методике: нагенерировав гуидов, представив их ссылками на справочник, запихнув в таблицу и связав со справочником выбирая максимум по существующим ссылкам в группировках по придуманным.
Сейчас попробую :)
РезультатВыборки = Новый Массив;
ПервоначальнаяТаблица = Новый ТаблицаЗначений;
ПервоначальнаяТаблица.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для СчЭлементов = 1 По НадоСлЭлементов Цикл
Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
ПервоначальнаяТаблица.Добавить().Товар = Номенклатура;
КонецЦикла;
Запросо = Новый Запрос;
Запросо.Текст = "ВЫБРАТЬ
| НедействительныеСсылки.Товар КАК Товар
|ПОМЕСТИТЬ Товары
|ИЗ
| &НедействительныеСсылки КАК НедействительныеСсылки
|
|ИНДЕКСИРОВАТЬ ПО
| Товар
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| МАКСИМУМ(ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка)) КАК Номенклатура,
| НедействительныеСсылки.Товар
|ИЗ
| Товары КАК НедействительныеСсылки
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
| ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
| ПО (ИСТИНА)
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО НедействительныеСсылки.Товар >= Номенклатура.Ссылка
| И (Номенклатура.ЭтоГруппа = ЛОЖЬ)
|
|СГРУППИРОВАТЬ ПО
| НедействительныеСсылки.Товар";
Запросо.УстановитьПараметр("НедействительныеСсылки",ПервоначальнаяТаблица);
//Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
РезЗапроса = Запросо.Выполнить();
Если Не РезЗапроса.Пустой() Тогда
СлучайныеТовары.ЗагрузитьЗначения(РезЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура"));
СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
КонецЕсли;
Показать
700 товаров менее чем за 2 секунды, есть повторения, но не первого элемента,
можно задавать 1300 товаров, сворачивать и 700 обрезать.
... результат в таблице, ВЫБРАТЬ РАЗЛИЧНЫЕ ... и
Файловая база 13 секунд 1300 неуникальных, 878 уникальных.
РезультатВыборки = Новый Массив;
ПервоначальнаяТаблица = Новый ТаблицаЗначений;
ПервоначальнаяТаблица.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для СчЭлементов = 1 По 2 * НадоСлЭлементов Цикл
Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
ПервоначальнаяТаблица.Добавить().Товар = Номенклатура;
КонецЦикла;
Запросо = Новый Запрос;
Запросо.Текст = "ВЫБРАТЬ
| НедействительныеСсылки.Товар КАК Товар
|ПОМЕСТИТЬ Товары
|ИЗ
| &НедействительныеСсылки КАК НедействительныеСсылки
|
|ИНДЕКСИРОВАТЬ ПО
| Товар
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| МАКСИМУМ(ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка)) КАК Номенклатура,
| НедействительныеСсылки.Товар
|ПОМЕСТИТЬ ВсякаБяка
|ИЗ
| Товары КАК НедействительныеСсылки
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
| ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ГДЕ
| Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
| ПО (ИСТИНА)
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО НедействительныеСсылки.Товар >= Номенклатура.Ссылка
| И (Номенклатура.ЭтоГруппа = ЛОЖЬ)
|
|СГРУППИРОВАТЬ ПО
| НедействительныеСсылки.Товар
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ " + Формат(НадоСлЭлементов, "ЧГ=") + "
| ВсякаБяка.Номенклатура
|ИЗ
| ВсякаБяка КАК ВсякаБяка";
Запросо.УстановитьПараметр("НедействительныеСсылки",ПервоначальнаяТаблица);
//Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
РезЗапроса = Запросо.Выполнить();
Если Не РезЗапроса.Пустой() Тогда
СлучайныеТовары.ЗагрузитьЗначения(РезЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура"));
СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
КонецЕсли;
Сообщить(СлучайныеТовары.Количество());
(87) vugluscr1991, - отлично!
Нужно сказать, что такой способ я не стал пробовать из-за того, что запрос, в котором было "УПОРЯДОЧИТЬ ПО Ссылка" вернул мне явно не случайный порядок. Теперь думаю, что если сформировать справочник, генерируя ему уникальные идентификаторы подобным образом, то порядок был бы случайным. Нужно будет проверить.
Получается, что 2 (13) секунды 700 случайных элементов (пусть с повторением). А сколько всего элементов было в справочнике?