Как в запросе выбрать из справочника несколько случайных элементов?

1. Сергей (ildarovich) 4842 29.03.15 11:06 Сейчас в теме
Один способ я знаю. Интересует: есть ли другие способы?
Вознаграждение за ответ
Показать полностью
Найденные решения
87. Паша Лаптев (vugluscr1991) 6 03.04.15 14:34 Сейчас в теме
Окончательно:
	РезультатВыборки = Новый Массив;
	
	ПервоначальнаяТаблица = Новый ТаблицаЗначений;
	ПервоначальнаяТаблица.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
	
	Для СчЭлементов = 1 По 2 * НадоСлЭлементов Цикл
		Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
		СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
		
		ПервоначальнаяТаблица.Добавить().Товар = Номенклатура;
	КонецЦикла;
	
	
		Запросо = Новый Запрос;
		Запросо.Текст = "ВЫБРАТЬ
		                |	НедействительныеСсылки.Товар КАК Товар
		                |ПОМЕСТИТЬ Товары
		                |ИЗ
		                |	&НедействительныеСсылки КАК НедействительныеСсылки
		                |
		                |ИНДЕКСИРОВАТЬ ПО
		                |	Товар
		                |;
		                |
		                |////////////////////////////////////////////////////////////­////////////////////
		                |ВЫБРАТЬ
		                |	МАКСИМУМ(ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка)) КАК Номенклатура,
		                |	НедействительныеСсылки.Товар
		                |ПОМЕСТИТЬ ВсякаБяка
		                |ИЗ
		                |	Товары КАК НедействительныеСсылки
		                |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
		                |			Номенклатура.Ссылка КАК Ссылка
		                |		ИЗ
		                |			Справочник.Номенклатура КАК Номенклатура
		                |		ГДЕ
		                |			Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
		                |		ПО (ИСТИНА)
		                |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
		                |		ПО НедействительныеСсылки.Товар >= Номенклатура.Ссылка
		                |			И (Номенклатура.ЭтоГруппа = ЛОЖЬ)
		                |
		                |СГРУППИРОВАТЬ ПО
		                |	НедействительныеСсылки.Товар
		                |;
		                |
		                |////////////////////////////////////////////////////////////­////////////////////
		                |ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ " + Формат(НадоСлЭлементов, "ЧГ=") + "
		                |	ВсякаБяка.Номенклатура
		                |ИЗ
		                |	ВсякаБяка КАК ВсякаБяка";
		
		Запросо.УстановитьПараметр("НедействительныеСсылки",ПервоначальнаяТаблица);				
		//Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
		
		РезЗапроса = Запросо.Выполнить();
		Если Не РезЗапроса.Пустой() Тогда
		
			СлучайныеТовары.ЗагрузитьЗначения(РезЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура"));
			СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
		КонецЕсли;
		
		Сообщить(СлучайныеТовары.Количество());
...Показать Скрыть
Остальные ответы
2. sssssssssssssss sssssssssssssss (sssss_aaaaa_2011) 29.03.15 13:07 Сейчас в теме
И как определить принадлежность способа к категории "другие" при отсутствии знаний о категории "не другие"?
3. Максим Биенко (Bienko) 109 29.03.15 13:32 Сейчас в теме
Для этого в базе и есть генератор случайных чисел...
4. Олег (Lovish) 29.03.15 13:46 Сейчас в теме
(2) sssss_aaaaa_2011, наверняка автор имеет в виду получение с помощью ГенераторСлучайныхЧисел: пронумеровать все элементы справочника от 1 до КоличествоЭлементов, получить нужное количество случайных номеров в диапазоне от 1 до КоличествоЭлементов, получить нужные элементы по этим случайным номерам.
5. Сергей (ildarovich) 4842 29.03.15 16:13 Сейчас в теме
(2) sssss_aaaaa_2011, сойдет любой работающий В ЗАПРОСЕ способ. Свой способ я отличу.
6. Сергей (ildarovich) 4842 29.03.15 16:15 Сейчас в теме
(3) Bienko, "в базе" генератора нет, к сожалению. В языке запросов, я имею ввиду нет, а решение нужно именно в запросе.
7. Сергей (ildarovich) 4842 29.03.15 16:18 Сейчас в теме
(4) Lovish, нумерация элементов - очень трудоемкий этап. Трудоемкость растет квадратично по отношению к числу элементов справочника. Попробуйте для примера пронумеровать в запросе свой справочник номенклатуры или контрагентов - результата придется ждать очень долго.
8. sssssssssssssss sssssssssssssss (sssss_aaaaa_2011) 29.03.15 17:25 Сейчас в теме
(5) ildarovich, спасибо, вы сделали мне большое одолжение озвучив таки хоть какие-то критерии оценки вариантов вашим величеством. :/
9. Василий Коровин (vasyak319) 122 29.03.15 18:05 Сейчас в теме
10. Петр Хохобашвили (piter2107@yandex.ru) 29.03.15 19:07 Сейчас в теме
Нумерация элементов очень трудоемкий этап.Попробуйте для примера пронумеровать в запросе свой справочник номенклатуры или контрагентов.
11. Михаил Зотов (ZOMI) 285 29.03.15 19:42 Сейчас в теме
Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Контрагенты.Ссылка,
		|	Контрагенты.Код
		|ИЗ
		|	Справочник.Контрагенты КАК Контрагенты
		|ГДЕ
		|	Контрагенты.Код ПОДОБНО &СлучайнаяСекунда";
		
 
	
	Запрос.УстановитьПараметр("СлучайнаяСекунда","%"+ Секунда(ТекущаяДата())+"%");
...Показать Скрыть
PowerBoy; ildarovich; +2 Ответить 4
12. TMV 14 29.03.15 19:49 Сейчас в теме
(11) ZOMI, дык ровно через минуту запрос вернет тот же результат. Разве это случайность?
13. Михаил Зотов (ZOMI) 285 29.03.15 19:57 Сейчас в теме
(12) TMV, где в задаче было условие "каждую минуту запросом получать случайный набор элементов"? ))

Я привел пример с секундой - можно усложнить играясь с текущим временем если запросы будут периодическими
14. Виктор Константинов (volga23rus) 29.03.15 21:39 Сейчас в теме
на инфостарте уже писали как случайное число сделать, в запрос параметр передать думаю не составит сложности
//НВЮ/ Получение Случайного Числа
//
// Параметры
//  <Мин>  - <Число> - Нижняя граница Равномерного Распределения
//  <Макс>  - <Число> - Верхняя граница Равномерного Распределения
//
// Возвращаемое значение:
//   <Число>   - Сгенерированное случайное число
//
Функция ПолучитьСлучайноеЧисло(Мин=0,Макс=100) Экспорт

//вместо Randomize 
Для н = 1 По Макс Цикл 
Уник = Новый УникальныйИдентификатор; 
КонецЦикла; 

//генерируем GUID 
Уник = СокрЛП(Новый УникальныйИдентификатор); 

//оставляем только цифры 
Уник    = СтрЗаменить(Уник,"-","");
Уник    = СтрЗаменить(Уник,Символы.НПП,"");

Случ = 0;
//знаменатель должен иметь такую же разрядность 
Знаменатель = 1; 
Для н = 1 По (СтрДлина(Уник)) Цикл
    ТекС = Сред(Уник,н,1);
    Если ТекС="a" Тогда
        Случ = Случ + Знаменатель*10;
    ИначеЕсли ТекС="b" Тогда
        Случ = Случ + Знаменатель*11;
    ИначеЕсли ТекС="c" Тогда
        Случ = Случ + Знаменатель*12;
    ИначеЕсли ТекС="d" Тогда
        Случ = Случ + Знаменатель*13;
    ИначеЕсли ТекС="e" Тогда
        Случ = Случ + Знаменатель*14;
    ИначеЕсли ТекС="f" Тогда
        Случ = Случ + Знаменатель*15;
    ИначеЕсли ТекС="1" Тогда
        Случ = Случ + Знаменатель;
    ИначеЕсли ТекС="2" Тогда
        Случ = Случ + Знаменатель*2;
    ИначеЕсли ТекС="3" Тогда
        Случ = Случ + Знаменатель*3;
    ИначеЕсли ТекС="4" Тогда
        Случ = Случ + Знаменатель*4;
    ИначеЕсли ТекС="5" Тогда
        Случ = Случ + Знаменатель*5;
    ИначеЕсли ТекС="6" Тогда
        Случ = Случ + Знаменатель*6;
    ИначеЕсли ТекС="7" Тогда
        Случ = Случ + Знаменатель*7;
    ИначеЕсли ТекС="8" Тогда
        Случ = Случ + Знаменатель*8;
    ИначеЕсли ТекС="9" Тогда
        Случ = Случ + Знаменатель*9;
    КонецЕсли;
    Знаменатель = Знаменатель * 16;
КонецЦикла; 

Случ = Случ / Знаменатель; //здесь получается дробное случайное число от 0 до 1 

//преобразуем его в случайное число из заданного интервала, округляем до целого 
ЧислоИзИнтервала = Мин(Макс(Окр(Мин + (Макс-Мин)*Случ),Мин),Макс); 

Возврат ЧислоИзИнтервала; 

КонецФункции //ПолучитьСлучайноеЧисло()
...Показать Скрыть
15. Василий Коровин (vasyak319) 122 29.03.15 22:33 Сейчас в теме
(14) volga23rus, а чем так плох встроенный в 1С датчик случайных чисел, что надо было эту жуткую функцию писать?
PowerBoy; Bienko; +2 Ответить
16. Виктор Константинов (volga23rus) 30.03.15 08:27 Сейчас в теме
ничем не плох, просто организатор обсуждения про один способ знает и просил что-нибудь аналогичное.
Думаю первый способ как раз и был: ГенераторСлучайныхЧисел
17. Ildar Gabdrakhmanov (spezc) 265 30.03.15 08:47 Сейчас в теме
в самом запросе случаное не получить, в любом случае, случайные числа нужно получать отдельно и передавать в запрос в виде параметров или в виде таблицы значений с числами. а там уже у кого как фантазия работает.
18. Азат (mar82) 30.03.15 09:07 Сейчас в теме
а если просто запрос типа "выбрать первые N ссылка из справочник.мойсправочник упорядочить по " а тут уже сортировку и направление случайным образом выбирать
19. Василий Коровин (vasyak319) 122 30.03.15 10:46 Сейчас в теме
(17) spezc, ну почему же - можно. Топикстартер стартанул таким тоном, что раскалываться не хотелось, но, видимо, что-то озвучить придётся :(
ГенераторСлучайныхЧисел не на волшебной пыльце работает, это обычные вычисления, которые можно проделать в запросе. Классический ГСЧ (дальше могу слегка напутать - последний раз занимался этим вопросом ещё в прошлом веке) это два нечётных (чтобы не накапливались нули в младших разрядах, что приведёт к вырождению ГСЧ) числа - seed и как_там_его_называют. Каждое обращение к ГСЧ происходит следующее:

как_там_его_называют=(seed*как_там_его_называют) % 2^разрядность;
Возврат как_там_его_называют;


Всего делов - передать в параметре запроса случайный seed, чтобы последовательные выполнения этого запроса приводили к разным результатам.
20. Сергей (necropunk) 4 30.03.15 10:48 Сейчас в теме
(17) spezc, ты статьи ildarovich по запросам читал же? По-моему, он запросами скоро задачи из курса высшей математики начнет решать, к этому все идет :) Хотя... Эммм... Он уже их решает вроде...
21. Сергей (ildarovich) 4842 30.03.15 10:54 Сейчас в теме
(16) volga23rus, нет, датчик случайных чисел не подходит, так как его нельзя использовать внутри запроса.
22. Сергей (ildarovich) 4842 30.03.15 11:16 Сейчас в теме
(17) spezc, тут я и хотел разнообразные фантазии увидеть. Даже если ввести таблицу случайных чисел или случайный параметр - что дальше со справочником делать? Тут уже предложили через "подобно" отбирать, но тогда некоторые коды могут иметь преимущество при выборе. А хотелось бы бОльшей случайности.
А возможно, кто-то и источник энтропии в запросе подскажет где взять. Если работа многопользовательская, то можно время последнего записанного документа использовать, но это крайне не надежно.
23. Сергей Смирнов (Serginio) 513 30.03.15 11:16 Сейчас в теме
24. Сергей (ildarovich) 4842 30.03.15 11:18 Сейчас в теме
(11) ZOMI, это почти то, что нужно, но есть подозрение, что некоторые коды при таком подходе будут иметь преимущество.
25. Сергей (ildarovich) 4842 30.03.15 11:24 Сейчас в теме
(23) Serginio, спасибо, отличная ссылка!!! Вот только в 1С не NewId не Rand нет.

Я еще на хабре видел похожее обсуждение Postgres. Выборка N случайных записей.
26. Nikoly Nik (Cool_vsi) 30.03.15 11:42 Сейчас в теме
		Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	Контрагенты.Ссылка
		|ИЗ
		|	Справочник.Контрагенты КАК Контрагенты
		|ГДЕ
		|	Контрагенты.ЭтоГруппа = ЛОЖЬ";

	Тз = Запрос.Выполнить().Выгрузить();

	Тз.Колонки.Добавить("Сортировка",Новый ОписаниеТипов("Число"));
	
	
	Для каждого строка из ТЗ цикл
		ГСЧ = Новый ГенераторСлучайныхЧисел;
	   Строка.Сортировка= ГСЧ.СлучайноеЧисло(0, 4294967295);
	КонецЦикла;
	
	Запрос2 = Новый Запрос;
	Запрос2.Текст = 
		"ВЫБРАТЬ
		|	кТ.Ссылка,
		|	кТ.Сортировка
		|ПОМЕСТИТЬ КТВ
		|ИЗ
		|	&Кт КАК кТ
		|;
		|
		|////////////////////////////////////////////////////////////­////////////////////
		|ВЫБРАТЬ ПЕРВЫЕ 5
		|	КТВ.Ссылка,
		|	КТВ.Сортировка КАК Сортировка
		|ИЗ
		|	КТВ КАК КТВ
		|
		|УПОРЯДОЧИТЬ ПО
		|	Сортировка";

	Запрос2.УстановитьПараметр("Кт", Тз);
	рез= Запрос2.Выполнить().Выбрать();
	Пока рез.Следующий() цикл
		Сообщить(рез.ссылка);
	КонецЦикла;


...Показать Скрыть


2 запрос выбирает случайные элементы =)

п.с. просьба сильно не бить ))
27. Василий Коровин (vasyak319) 122 30.03.15 11:47 Сейчас в теме
(22) ildarovich,
А возможно, кто-то и источник энтропии в запросе подскажет где взять


А просто передать в параметр значение одинэсовского ГСЧ чем плохо? Запрос всё-равно не в отдельной вселенной выполняется, туда по-любому можно параметр передать.
28. Василий Коровин (vasyak319) 122 30.03.15 11:50 Сейчас в теме
(26) Cool_vsi, а что, формально всё соблюдено. Как говорил Дядя Фёдор коту Матроскину: "Чтобы выбрать в запросе что-то случайное, надо сначала передать туда что-то случайное, а у нас в запросе ГСЧ нет".
WhiteOwl; +1 Ответить
29. Caponid V (caponid) 30.03.15 11:58 Сейчас в теме
все что можно написать из 1С (по моему мнению) - это проиндексировать выборку случайными значениями и потом выбрать N элементов с учетом сортировки - способ затратный получается.

Проще сделать прямой запрос к базе и получить в зависимости от вида SQL (NEWID()), Рostgree (Random()), db2(не помню, но тоже что то c RAND()) набор ID - в случае файловой остается чистый 1с например - выборка.Следующий и ГСЧ.

не универсально конечно.. но и ресурсы не резиновые - создания таблиц порождающими запросами да если еще и не в один поток - быстро загонит бд в ступор
30. Сергей (ildarovich) 4842 30.03.15 12:07 Сейчас в теме
(26) Cool_vsi, это будет работать, но все же это не метод "в запросе".
Кроме того, если уж выбрали весь справочник в память, нужно сразу выбирать из него элементы генерацией пяти случайных чисел (проверив, что они различные). Это будет гораздо быстрее, чем для каждой строки получить случайное число (а если строк 10 тысяч?), а затем эту огромную таблицу перегонять в запрос.
Тут как раз и видна проблема: для того, чтобы выбрать всего пять элементов, приходится выбирать все элементы справочника.
31. poyson (poyson) 30.03.15 12:09 Сейчас в теме
ну сгенерируй случайное число сам, например использовав текущую дату и время....
32. Сергей (ildarovich) 4842 30.03.15 12:13 Сейчас в теме
(29) caponid, для MSSQL и Postgre в комментариях (23) и (25) решения приведены. Видно, что с NewID() тоже не все так просто.

Порождающий запрос тут не собирался использовать, поэтому про "загонит БД в ступор" (в чем я сомневаюсь) спорить смысла нет.
33. Сергей (ildarovich) 4842 30.03.15 12:16 Сейчас в теме
(31) poyson, а что с этим числом дальше делать? Ведь задача: выбрать случайные элементы из справочника в запросе. Как для этого случайное число дальше использовать? Нужен текст запроса наподобие (11).
34. Сергей Иванов (Serg82) 17 30.03.15 12:33 Сейчас в теме
на основе уникального идентификатора получать случайные числа
35. Nikoly Nik (Cool_vsi) 30.03.15 12:38 Сейчас в теме
(30) ildarovich, я сам удивился но работает быстро, меньше секунды для 7000 элементов, формально исходя из название темы все условия соблюдены ..а реально да , это не 1 запрос..насчет выборки всех элементов, думаю если в запросе сделать несколько виртуальных таблиц,в которых будут все элементы то по скорости будет не намного быстрее...да сам хочу посмотреть на чистый запрос в 1с, который быстро случайно выберет n элементов...
36. Евгений Ванжула (minimajack) 32 30.03.15 12:49 Сейчас в теме
ВЫБРАТЬ
	СотрудникиОрганизаций.Ссылка КАК НомерСтроки,
	ПОДСТРОКА(СотрудникиОрганизаций.Код, 0, 10) КАК Строка
ПОМЕСТИТЬ Дано
ИЗ
	Справочник.СотрудникиОрганизаций КАК СотрудникиОрганизаций
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ 0 С,    1 КАК П
    ПОМЕСТИТЬ Р16
   ОБЪЕДИНИТЬ ВЫБРАТЬ  1, 10
   ОБЪЕДИНИТЬ ВЫБРАТЬ  2, 100
   ОБЪЕДИНИТЬ ВЫБРАТЬ  3, 1000
   ОБЪЕДИНИТЬ ВЫБРАТЬ  4, 10000
   ОБЪЕДИНИТЬ ВЫБРАТЬ  5, 100000
   ОБЪЕДИНИТЬ ВЫБРАТЬ  6, 1000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ  7, 10000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ  8, 100000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ  9, 1000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 10, 10000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 11, 100000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 12, 1000000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 13, 10000000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 14, 100000000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 15, 1000000000000000
   ОБЪЕДИНИТЬ ВЫБРАТЬ 16, 10000000000000000;


////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	Дано.НомерСтроки,
	СУММА(А.П * Б.С * ВЫБОР
			КОГДА ПОДСТРОКА(Дано.Строка, 1, 17 - А.С) ПОДОБНО "%.%"
				ТОГДА 10
			ИНАЧЕ 1
		КОНЕЦ) / МИНИМУМ(ВЫБОР
			КОГДА НЕ ПОДСТРОКА(Дано.Строка, 1, 17 - А.С) ПОДОБНО "%.%"
				ТОГДА А.П
			ИНАЧЕ 100000000000000000
		КОНЕЦ) КАК Ответ
ПОМЕСТИТЬ Результат
ИЗ
	Дано КАК Дано,
	Р16 КАК А,
	Р16 КАК Б
ГДЕ
	Б.С < 10
	И ПОДСТРОКА(Дано.Строка, 17 - А.С, 1) = ПОДСТРОКА("0123456789", Б.С + 1, 1)

СГРУППИРОВАТЬ ПО
	Дано.НомерСтроки
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ ПЕРВЫЕ 5
	Результат.НомерСтроки,
	Результат.Ответ,
	((ВЫРАЗИТЬ(Результат.Ответ / &Сид КАК ЧИСЛО(10, 0)) - ВЫРАЗИТЬ(Результат.Ответ / &Сид КАК ЧИСЛО(10, 5)))) КАК Поле1
ИЗ
	Результат КАК Результат

УПОРЯДОЧИТЬ ПО
	Поле1
...Показать Скрыть

Использование остатка от деления на случайное число как сортировку
ildarovich; +1 Ответить 2
37. Nikoly Nik (Cool_vsi) 30.03.15 12:55 Сейчас в теме
(36) minimajack, я так понимаю что при сид=постоянное значению(попробовал разные варианты сид при одинаковых вариантах сид рез одинаков), то и выводиться будут тоже самое. Вариант 11 такойже только лаконичнее. Рандом число все-равно передается в запрос, и все пляшет от него.
38. Евгений Ванжула (minimajack) 32 30.03.15 13:05 Сейчас в теме
(37) Cool_vsi,
1 принцип разный
2 где написано что при одинаковом сиде должны быть разные результаты?
39. Alexandr Kuritsyn (hibico) 210 30.03.15 13:11 Сейчас в теме
Если не передавать в запрос случайные значения, то можно только ориентироваться на какие-то изменения в базе. Например, как писалось выше на время создания, версию данных последнего документа или на количество каких-то записей. Но если с данными ничего не происходит, то вариантов нет.
40. Nikoly Nik (Cool_vsi) 30.03.15 13:11 Сейчас в теме
(38) minimajack, общий принцип одинаковый, передаем случайное число получаем случайное, вариантов на самом деле очень много если передавать случайное число...я думаю всем интересен запрос, который сам будет генерировать случайный элементы без передачи в него случайных чисел, ваш вариант интересен с математической точки зрения...но с точки зрения скорости работы и принципа если есть вариант проще не стоит загоняться, ваш вариант проигрывает другим вариантом с прицыпом передачи в запрос случайного числа...
41. Петр Петренко (PetroP) 30.03.15 13:14 Сейчас в теме
Расскажите хоть один способ без передачи параметра в запрос. Критерий случайности - не повторение выборки при одинаковой ИБ.
minimajack; +1 Ответить
42. Сергей (ildarovich) 4842 30.03.15 13:28 Сейчас в теме
(36) minimajack, хороший вариант. Его еще можно улучшить, если код-число преобразовывать по-другому. По формуле (А * Код + B) % 2^32, где A, B - некоторые "большие числа". Примеры "хороших" чисел можно посмотреть у Кнута. Например, А = 1664525, B = 0.
43. Сергей (ildarovich) 4842 30.03.15 13:35 Сейчас в теме
(39) hibico, вообще говоря, можно создать небольшую временную таблицу, где хранить номер итерации, увеличивая его при каждой следующей случайной выборке.
Но, конечно, хочется чего-либо типа времени, объема свободной памяти, всего, что может быть настоящим источником энтропии. ...блокировки?...
44. Евгений Ванжула (minimajack) 32 30.03.15 13:47 Сейчас в теме
(43) ildarovich, в доступных функциях запроса ничего не доступно, так что хоть тысячу раз запускай - ничего не изменится и во временных таблицах...причина этому - детерминированность алгоритмов - фактически это закон для компьютера. У нас не квантовые компьютеры - так что без внешнего источника энтропии - рыпаться бесполезно.
Если есть возможность сгенерировать до запроса, есть МенеджерКриптографии - там и парится не надо.
45. Евгений Ванжула (minimajack) 32 30.03.15 14:20 Сейчас в теме
ВЫБРАТЬ
	Контрагенты.Ссылка КАК Ссылка,
	Контрагенты.Код КАК Код,
	КОЛИЧЕСТВО(Контрагенты.Код) * 0 КАК Индекс
ПОМЕСТИТЬ ВТ_ДАННЫЕ
ИЗ
	Справочник.Контрагенты КАК Контрагенты
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты1
		ПО Контрагенты.Ссылка >= Контрагенты1.Ссылка

СГРУППИРОВАТЬ ПО
	Контрагенты.Ссылка,
	Контрагенты.Код

ИНДЕКСИРОВАТЬ ПО
	Индекс
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ ПЕРВЫЕ 5
	ВТ_ДАННЫЕ.Ссылка,
	ВТ_ДАННЫЕ.Код,
	ВТ_ДАННЫЕ.Индекс
ИЗ
	ВТ_ДАННЫЕ КАК ВТ_ДАННЫЕ

УПОРЯДОЧИТЬ ПО
	ВТ_ДАННЫЕ.Индекс
...Показать Скрыть

Нашел!!! =))
Индексирование наше все )) для скульной базы работает
46. Ёпрст (Ёпрст) 1015 30.03.15 14:28 Сейчас в теме
(45) И чего ты нашел ?
И где тут случайность ?
Простейший примитив, как сделать нумерацию в тексте запроса.. не более того.
47. Ёпрст (Ёпрст) 1015 30.03.15 14:29 Сейчас в теме
И это, индексировать в этом запросе не обязательно
48. Евгений Ванжула (minimajack) 32 30.03.15 14:29 Сейчас в теме
(46) Ёпрст, проверил?
(47) как раз именно вариант с подзапросом с индексированием виртуального нуля дает случайную выборку
зы индексировать не обязательно =)
что бы не смущало
КОЛИЧЕСТВО(Контрагенты.Код) * 0 КАК Индекс

заменить на
КОЛИЧЕСТВО(0) * 0 КАК Индекс
49. Nikoly Nik (Cool_vsi) 30.03.15 14:34 Сейчас в теме
(45) minimajack, проверил выбираем 4-5 боле менее рандом, выбираем 1000 уже не рандом....
50. Ёпрст (Ёпрст) 1015 30.03.15 14:38 Сейчас в теме
(48)Проверил. Выборка всегда одинаковая.
51. Nikoly Nik (Cool_vsi) 30.03.15 14:40 Сейчас в теме
(50) Ёпрст, странно у меня когда 4-5 через раз, то рандом(хотя некоторые элементы очень часто повторяются в отличии от других)то также...
52. Ёпрст (Ёпрст) 1015 30.03.15 14:41 Сейчас в теме
(51) я хз, че у тебя там за база, но на sql не будет рандома в этом случае, никогда
53. Ёпрст (Ёпрст) 1015 30.03.15 14:42 Сейчас в теме
ну, разве что top 5 может иногда дать не тот вариант, если статистику обновить и все кеши сбросить
54. Nikoly Nik (Cool_vsi) 30.03.15 14:42 Сейчас в теме
(52) Ёпрст, у меня sql база, и когда выборка 4-5 значений выбираются разные при разных выполнениях
55. Евгений Ванжула (minimajack) 32 30.03.15 14:44 Сейчас в теме
(52) Ёпрст, любой рандом относительный...это же не криптография
поговорим у кого рандом у кого нет?
по условиям задачи все выполнено
56. Ёпрст (Ёпрст) 1015 30.03.15 14:45 Сейчас в теме
(55) С фигали выполнено, если не воспроизводится ?
И.. в (0) нет ни слова об использованиии СУБД.. для скуля, вообще проще rand() использовать и привет.
57. Ёпрст (Ёпрст) 1015 30.03.15 14:46 Сейчас в теме
(54) у меня тоже sql 2008 и результат всегда одинаковый.
58. Евгений Ванжула (minimajack) 32 30.03.15 15:17 Сейчас в теме
(56) Ёпрст, согласен не всегда воспроизводится, на базе с > 5000 записей работает, на маленькой выборке результат один и тот же...жаль, видимо остается в кэше...
59. Марат Хафизов (Painted) 16 30.03.15 15:43 Сейчас в теме
(54) Cool_vsi,
у меня sql база, и когда выборка 4-5 значений выбираются разные при разных выполнениях

У меня sql 2008, выборка 5 элементов. Выборка повторяется в среднем через 3-4 итерации, иногда подряд идут. Но забавно, система не улавливается. )))
60. Пользователь Инфостарта (infostart user) 14 30.03.15 16:53 Сейчас в теме
61. reznic Резник (reznic) 91 30.03.15 19:29 Сейчас в теме
а без генератора случайных чисел можно? и как быть если ты не попадешь в номер элемента?
62. Василий Коровин (vasyak319) 122 30.03.15 19:42 Сейчас в теме
(61) reznic,
а без генератора случайных чисел можно?
можно, но тогда выборка не будет случайной, поэтому нельзя
и как быть если ты не попадешь в номер элемента?
а для этого случайное число надо нормировать. Типа вот так:
НомерЭлемента=СлучайноеЧисло*КоличествоЭлементов/МаксимальноеСлучайноеЧисло
63. Евгений Ванжула (minimajack) 32 30.03.15 21:25 Сейчас в теме
(62) vasyak319,
а для этого случайное число надо нормировать. Типа вот так: 

огорчу...нормирование не поможет
либо перенумеровать случайные числа, либо случайное число получить из объекта(реквизита)
64. pavel ev (pavelyar) 31.03.15 00:53 Сейчас в теме
Выборка всегда одинаковая ?
65. Alexandr Kuritsyn (hibico) 210 31.03.15 10:07 Сейчас в теме
Ну если передавать через параметр случайное число нельзя, тогда можно создать какой-то объект (или использовать существующий), например регистр сведений, и с какой-нибудь периодичностью заполнять его новым случайным числом (числами). А в запросе выбирать данный объект и на его основе делать выборку элементов.
66. Vit IVA (1vasia1) 15 31.03.15 11:14 Сейчас в теме
А что если формировать результат запроса по курсам валют )
67. Сергей Смирнов (Serginio) 513 31.03.15 15:04 Сейчас в теме
(25) Ну если очень хочется, то прямой запрос в руки. Сам часто использую для объединения стороннх данных и регистра сведений через Merge. А там миллионы записей.
68. Nikoly Nik (Cool_vsi) 31.03.15 15:06 Сейчас в теме
варианты привязки к коду номера элемента как к цифрам бред, не везде в коде есть цифры, или например еше есть буквы, или только буквы...пока считаю лучшим вариантом мой...абсолютный рандом =)
69. Сергей (ildarovich) 4842 31.03.15 15:53 Сейчас в теме
(68) Cool_vsi, метод, приведенный в (26) слабо соответствует условиям задачи. Главное в условии - сделать выбор "в запросе". У вас же основные действия, а именно, добавление колонки со случайными числами, производятся вне запроса.

То есть последовательность у вас такова:
1) выбираем ВЕСЬ справочник в таблицу значений;
2) добавляем колонку и записываем в каждый элемент новой колонки случайное число;
3) возвращаем ВЕСЬ справочник с добавленной колонкой в запрос;
4) сортируем по рандомному столбцу;
5) отбираем первые 5.

Если убрать из вашего алгоритма явно избыточные (абсолютно лишние) действия, то должен остаться алгоритм:
1) выбираем ВЕСЬ справочник в таблицу значений;
2) выбираем с помощью ГСЧ из таблицы значений 5 разных элементов;
3) возвращаем выбранные случайные элементы в запрос.

то станет очевидным, где на самом деле делается случайный выбор.

Вот, например, в статье "Порождающий запрос" есть запрос, формирующий временную таблицу псевдослучайных чисел прямо в запросе. То есть проблемы получения таблицы псевдослучайных чисел в запросе нет. Проблема в том, чтобы соединить ее с таблицей справочника, не выводя их из запроса. Вы этот вопрос обошли, нарушив (по моему мнению) условия задачи.

С другой стороны, предложенный в (26) метод (с учетом поправок) очевиден и для практики совершенно нормален (единственно возможен?), если не задано условие "в запросе".
70. Nikoly Nik (Cool_vsi) 31.03.15 16:02 Сейчас в теме
(69) ildarovich, я не спорю что мой вариант не совсем подходит под условия задачи. Но варианты с передачей в запрос случайного числа и привязке к коду еще большее не подходят на мой взгляд.Самому интересно решение данного вопроса
71. Caponid V (caponid) 01.04.15 11:06 Сейчас в теме
как вариант... не нравится мне все таки идея с запросом в котором все...
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	Номенклатура.Ссылка,
	|	КОЛИЧЕСТВО(Номенклатура1.Код) КАК НомерСтроки
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|		ПОЛНОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура1
	|		ПО (Номенклатура.Код >= Номенклатура1.Код)
	|
	|СГРУППИРОВАТЬ ПО
	|	Номенклатура.Ссылка";
	
	РезультатЗапроса = Запрос.Выполнить();
	Выборка = РезультатЗапроса.Выбрать();
	
	Граница = Выборка.Количество();
	ГСЧ = Новый ГенераторСлучайныхЧисел(ТекущаяДата());
	
	КоличествоСлучайных = 5;
	сч = 1;
	
	ТЗ = Новый ТаблицаЗначений;
	ТЗ.Колонки.Добавить("Ссылка"); 
	
	Пока сч <= КоличествоСлучайных Цикл
		Индекс = ГСЧ.СлучайноеЧисло(1, Граница);	
		Выборка.НайтиСледующий(Новый Структура("НомерСтроки",Индекс));
		НоваяСтрока = ТЗ.Добавить();
		НоваяСтрока.Ссылка = Выборка.Ссылка;
		сч = сч +1;
	КонецЦикла; 
...Показать Скрыть
72. Александр Полтава (Патриот) 179 01.04.15 11:17 Сейчас в теме
Какие вообще есть варианты?
В общем случае внутри запроса 1С получить случайное число невозможно (в частном случае, есть разные варианты – например, считать количество каких-либо постоянно добавляемых элементов справочника или смотреть какой-то объект в базе, куда мы постоянно специально будем записывать случайное число).
Следовательно, при выполнении запроса придётся каждый раз передавать случайное число (назову его Rand), т.е. при инициализации запроса одним и тем же случайным числом мы получим одни и те же "случайные" данные.
Итак, мы передали в запрос случайное число, что дальше?
Чтобы решение было универсальным мы можем привязаться только к стандартным реквизитам (других в справочнике просто может и не быть).
Из стандартных реквизитов подходит нам всего два - это уникальный "код" и относительно случайное "наименование". (С "ссылкой" мы никаких операций в запросе не сможем провести, поэтому она не подходит. Остальные реквизиты не обеспечивают практически никакой случайности, хотя если добавить и их, то случайность как минимум не понизится, но это замедлит процесс вычисления.)
Какой бы путь мы не выбрали нам всё равно придётся генерировать некий ключ на основе реквизитов "код" и "наименование" (в документах была бы ещё и "дата"). И ключ этот должен быть числовой, чтобы далее взаимодействовать с Rand.
Алгоритм вычисления ключа: Допустим и "наименование" и "код" имеют тип "строка". Чтобы обеспечить перевод строк в числа, нам понадобится временная таблица кодировки символов (с полями "Символ" и "Число") и функция "ПОДСТРОКА". Таким образом, выбирая символ, мы сразу сопоставляем ему число. Ну а далее из этих чисел по какой-нибудь хитрой формуле считаем ключ. Например, перемножаем все числа между собой (что-то у меня фантазия ещё не разогрелась).
Имея у каждого элемента справочника уникальный числовой ключ и случайное число, которым мы инициализировали запрос, выбрать случайные несколько элементов уже проще. Например, считаем поле «Порядок» как остаток от деления «ключа» на «Rand» (с помощью функции «Выразить»). Далее упорядочиваем по полю «Порядок» и выбираем первые N.
ildarovich; +1 Ответить 2
73. Александр Терехин (anterehin) 12 01.04.15 11:21 Сейчас в теме
Давно наблюдаю за темой.. прочитал последний топик, где вопрос возникает как взять некое число рандом..
А если рассмотреть в запросе РазностьДат? Т.е. Некая константа.. Дата регистрации организации и текущая дата.
74. Александр Полтава (Патриот) 179 01.04.15 11:27 Сейчас в теме
(73) anterehin,
1. отнимая от текущей даты константу случайность не повысится, т.е. легче просто взять текущую дату.
2. текущую дату надо в запрос передать, т.к. внутри её не вычислить.
3. "Дата регистрации организации" скорее всего есть не в каждой базе, т.е. это ограничивает универсальность
75. Caponid V (caponid) 01.04.15 11:27 Сейчас в теме
или вот еще вариант
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	КОЛИЧЕСТВО(Номенклатура.Ссылка) КАК ИндексВыборки
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	НЕ Номенклатура.ЭтоГруппа";
	ТЗ = Запрос.Выполнить().Выгрузить();
	
	Граница = ТЗ[0].ИндексВыборки;
	ТЗ.Очистить();
	ГСЧ = Новый ГенераторСлучайныхЧисел(ТекущаяДата());
	
	КоличествоСлучайных = 5;
	сч = 1;
	
	Пока сч <= КоличествоСлучайных Цикл
		Индекс = ГСЧ.СлучайноеЧисло(0, Граница);	
		НоваяСтрока = ТЗ.Добавить();
		НоваяСтрока.ИндексВыборки = Индекс;
		сч = сч +1;
	КонецЦикла; 
	 
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	ВнешняяТаблица.ИндексВыборки
	|ПОМЕСТИТЬ ВТВыборки
	|ИЗ
	|	&ТЗ КАК ВнешняяТаблица
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	Номенклатура.Ссылка,
	|	КОЛИЧЕСТВО(Номенклатура1.Код) КАК НомерСтроки
	|ПОМЕСТИТЬ ВТДанные
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|		ПОЛНОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура1
	|		ПО Номенклатура.Код >= Номенклатура1.Код
	|ГДЕ
	|	НЕ Номенклатура.ЭтоГруппа
	|
	|СГРУППИРОВАТЬ ПО
	|	Номенклатура.Ссылка
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	ВТДанные.Ссылка
	|ИЗ
	|	ВТВыборки КАК ВТВыборки
	|		ЛЕВОЕ СОЕДИНЕНИЕ ВТДанные КАК ВТДанные
	|		ПО ВТВыборки.ИндексВыборки = ВТДанные.НомерСтроки";
	
	Запрос.УстановитьПараметр("ТЗ", ТЗ);
	
	ТЗ = Запрос.Выполнить().Выгрузить();
...Показать Скрыть
76. Caponid V (caponid) 01.04.15 11:29 Сейчас в теме
(72) Патриот, ссылка тоже псевдо уникальная - гуиды то пакетами (вроде 20 на сессию) выдаются по возрастанию...
77. Давид Каспаров (Deveruchi) 01.04.15 11:31 Сейчас в теме
Тут видется только использование времени в качестве псевдослучайного элемента.
78. Александр Полтава (Патриот) 179 01.04.15 11:36 Сейчас в теме
(76) caponid, я писал, что
С "ссылкой" мы никаких операций в запросе не сможем провести, поэтому она не подходит
79. Петр Петренко (PetroP) 01.04.15 11:42 Сейчас в теме
(77) Deveruchi, какая разница, что использовать, если это надо передавать параметром в запрос?
Все еще считаю, что нет способов.
80. Сергей (ildarovich) 4842 01.04.15 11:59 Сейчас в теме
(72) Патриот, все логично, примерно так у меня и сделано. Я, в общем-то, задал вопрос для проверки: не пропустил ли я какой-либо более простой вариант решения этой задачи или нет ли какой свежей идеи. Ссылку на свое решение специально не привел, чтобы не затормозить приток идей.
Для меня обсуждение оказалось полезным по нескольким причинам:
- в комментарии (11) предложена свежая идея использование оператора "ПОДОБНО". Если бы можно обеспечить "ортогональность" сравнения через "ПОДОБНО" кодов справочника с несколькими базисными строками (чтобы результат сравнения делил справочник примерно пополам и для каждой базисной строки деление было бы независимым), то можно было бы развить этот подход;
- в комментарии (23) приведена полезная ссылка, которая напомнила, как можно ускорить решение, сократив затраты на сортировку. В результате смог еще ускорить свое решение;
- в комментарии (45) приведена одна из возможностей нахождения источника энтропии в запросе (правда, не надежная) и остается небольшая надежда, что, вдруг, есть и другие.
Патриот; +1 Ответить
81. Сергей (ildarovich) 4842 01.04.15 12:28 Сейчас в теме
(71) (75) caponid, совершенно лишняя нумерация справочника в запросе. Это тяжелая операция, которая требует соединения справочника с собой. Если разрешить себе выбор вне запроса (что не соответствует условию), то лучше делать так
Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, 0 КАК Отбор ИЗ Справочник.Номенклатура ГДЕ НЕ ЭтоГруппа");
ВсеСсылки = Запрос.Выполнить().Выгрузить();
ГСЧ = Новый ГенераторСлучайныхЧисел();
Пока ВсеСсылки.Итог("Отбор") < 5 Цикл
		ВсеСсылки[ГСЧ.СлучайноеЧисло(0, ВсеСсылки.Количество() - 1)].Отбор = 1
КонецЦикла;
Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ Справочник.Номенклатура ГДЕ Ссылка В (&ОтборныеСсылки)");
Запрос.УстановитьПараметр("ОтборныеСсылки", ВсеСсылки.Скопировать(Новый Структура("Отбор", 1)));
Запрос.Выполнить().Выгрузить().ВыбратьСтроку("Случайные элементы:")
...Показать Скрыть
Конечно, в практическом применении нужно учесть, что справочник может содержать менее 5 элементов и проверять зацикливание, ну и обеспечить выбор пяти РАЗЛИЧНЫХ ссылок вообще не через долгий подсчет, а через соответствие.
82. Андрей Киреев (FractonKireyev) 01.04.15 17:48 Сейчас в теме
Я сделал-бы что-то вроде:
Запрос = Новый Запрос;
Запрос.Текст = "Выбрать Спр.Ссылка ИЗ Справочник.Контрагенты ГДЕ ...";    // Условие не пишу. Любое, которое нужно
Выборка = Запрос.Выполнить.Выбрать();

МассивСлучайныхЧисел = ПолучитьМассивСлучайныхЧисел();
// Функция "ПолучитьМассивСлучайныхЧисел()" должна возвращать массив случайных чисел
// от 0 (включая) до 1 (не включая) в нужном для задачи количестве.
// Как сгенерировать случайное число - обсуждать не хочу, в этой ветке предложено много хороших вариантов,
// кроме того в интернете очень много алгоритмов на эту тему.

Для каждого СлучайноеЧисло из МассивСлучайныхЧисел Цикл
    СлучайнаяСсылка = Выборка.Получить( Цел( СлучайноеЧисло * Выборка.Количество() ) );
    Сообщить( Строка( СлучайнаяСсылка ) );
КонецЦикла;
...Показать Скрыть


В результате всё решается в один запрос, без промежуточных таблиц и без анализа значений реквизитов справочника (в конце концов, разработчик может установить для кода или для наименования нулевую длину, и тогда просто нечего будет анализировать).
83. ramzess (ramzess) 02.04.15 08:36 Сейчас в теме
прямой скульный запрос вида SEL ECT * FR OM spravochnik WHERE Uslovine=5 ORDER BY rand() LIMIT 10
84. Паша Лаптев (vugluscr1991) 6 03.04.15 12:58 Сейчас в теме
(81) ildarovich,
"тяжелая операция соединения справочника с собой" - может быть и не так тяжела как выгрузка справочника в ТЗ. Надо сравнить в профайлере хотябы для SQL.
85. Паша Лаптев (vugluscr1991) 6 03.04.15 13:55 Сейчас в теме
	РезультатВыборки = Новый Массив;
	
	Для СчЭлементов = 1 По НадоСлЭлементов Цикл
		Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
		СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
		
		Запросо = Новый Запрос;
		Запросо.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
		                |	ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка) КАК Номенклатура
		                |ИЗ
		                |	Справочник.Номенклатура КАК Номенклатура
		                |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
		                |			Номенклатура.Ссылка КАК Ссылка
		                |		ИЗ
		                |			Справочник.Номенклатура КАК Номенклатура
		                |		ГДЕ
		                |			Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
		                |		ПО (ИСТИНА)
		                |ГДЕ
		                |	Номенклатура.Ссылка >= &Ссылка
		                |	И НЕ Номенклатура.Ссылка В (&Массиво)
		                |	И Номенклатура.ЭтоГруппа = ЛОЖЬ";
		
		Запросо.УстановитьПараметр("Ссылка", Номенклатура);
		Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
		
		РезЗапроса = Запросо.Выполнить();
		Если Не РезЗапроса.Пустой() Тогда
		
			Номенклатура = РезЗапроса.Выгрузить()[0].Номенклатура;
			РезультатВыборки.Добавить(Номенклатура);
		КонецЕсли;
	КонецЦикла;
	
	СлучайныеТовары.ЗагрузитьЗначения(РезультатВыборки);
	СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
...Показать Скрыть

Кажется, что первый элемент будет часто попадаться - но это лишь дыра в воображении. И тесты и разброс GUID-ов показывают, что все очень равномерно. Могут возникнуть трудности с количеством элементов сравнимым с мощностью справочника (быстродействие) - серия последовательных запросов ведет себя медленнее одного запроса сразу с таблицей внутри,
который можно сделать следуя данной методике: нагенерировав гуидов, представив их ссылками на справочник, запихнув в таблицу и связав со справочником выбирая максимум по существующим ссылкам в группировках по придуманным.
Сейчас попробую :)
ildarovich; +1 Ответить
86. Паша Лаптев (vugluscr1991) 6 03.04.15 14:21 Сейчас в теме
	РезультатВыборки = Новый Массив;
	
	ПервоначальнаяТаблица = Новый ТаблицаЗначений;
	ПервоначальнаяТаблица.Колонки.Добавить("Товар", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
	
	Для СчЭлементов = 1 По НадоСлЭлементов Цикл
		Номенклатура = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор());
		СслкаИД = Номенклатура.УникальныйИдентификатор(); // Нового().УникальныйИдентификатор();
		
		ПервоначальнаяТаблица.Добавить().Товар = Номенклатура;
	КонецЦикла;
	
	
		Запросо = Новый Запрос;
		Запросо.Текст = "ВЫБРАТЬ
		                |	НедействительныеСсылки.Товар КАК Товар
		                |ПОМЕСТИТЬ Товары
		                |ИЗ
		                |	&НедействительныеСсылки КАК НедействительныеСсылки
		                |
		                |ИНДЕКСИРОВАТЬ ПО
		                |	Товар
		                |;
		                |
		                |////////////////////////////////////////////////////////////­////////////////////
		                |ВЫБРАТЬ
		                |	МАКСИМУМ(ЕСТЬNULL(Номенклатура.Ссылка, ПервыйЭлемент.Ссылка)) КАК Номенклатура,
		                |	НедействительныеСсылки.Товар
		                |ИЗ
		                |	Товары КАК НедействительныеСсылки
		                |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ ПЕРВЫЕ 1
		                |			Номенклатура.Ссылка КАК Ссылка
		                |		ИЗ
		                |			Справочник.Номенклатура КАК Номенклатура
		                |		ГДЕ
		                |			Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ПервыйЭлемент
		                |		ПО (ИСТИНА)
		                |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
		                |		ПО НедействительныеСсылки.Товар >= Номенклатура.Ссылка
		                |			И (Номенклатура.ЭтоГруппа = ЛОЖЬ)
		                |
		                |СГРУППИРОВАТЬ ПО
		                |	НедействительныеСсылки.Товар";
		
		Запросо.УстановитьПараметр("НедействительныеСсылки",ПервоначальнаяТаблица);				
		//Запросо.УстановитьПараметр("Массиво", РезультатВыборки);
		
		РезЗапроса = Запросо.Выполнить();
		Если Не РезЗапроса.Пустой() Тогда
		
			СлучайныеТовары.ЗагрузитьЗначения(РезЗапроса.Выгрузить().ВыгрузитьКолонку("Номенклатура"));
			СлучайныеТовары.СортироватьПоЗначению(НаправлениеСортировки.Возр);
		КонецЕсли;
...Показать Скрыть

700 товаров менее чем за 2 секунды, есть повторения, но не первого элемента,
можно задавать 1300 товаров, сворачивать и 700 обрезать.
... результат в таблице, ВЫБРАТЬ РАЗЛИЧНЫЕ ... и
Файловая база 13 секунд 1300 неуникальных, 878 уникальных.
88. Andrew Schukin (Vint_1c) 15 03.04.15 14:43 Сейчас в теме
Вот мой вариант накиданный на скорую руку, всегда выдает случайность.

	ТекстЗапроса = "
	|ВЫБРАТЬ
	|	КОЛИЧЕСТВО(Контрагенты.Ссылка) КАК КОЛ
	|ИЗ
	|	Справочник.Контрагенты КАК Контрагенты
	|;";
	
	Запрос = Новый Запрос;
	Запрос.Текст = ТекстЗапроса;
	ВЫБОРКА = Запрос.Выполнить().Выбрать();
	ВЫБОРКА.Следующий();
	КолВСправочнике = ВЫБОРКА.Кол;
	
	ГенераторСЧ = Новый ГенераторСлучайныхЧисел;
	ЧислоСЧ = ГенераторСЧ.СлучайноеЧисло(1,КолВСправочнике);
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	Контрагенты.Ссылка,
	|	1 КАК НомерСтроки
	|ПОМЕСТИТЬ ВТ
	|ИЗ
	|	Справочник.Контрагенты КАК Контрагенты
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	Контрагенты.Ссылка,
	|	СУММА(ВТ.НомерСтроки) КАК НомерСтроки
	|ПОМЕСТИТЬ ВТКонтрагентыНумерация
	|ИЗ
	|	Справочник.Контрагенты КАК Контрагенты
	|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ КАК ВТ
	|		ПО Контрагенты.Ссылка <= ВТ.Ссылка
	|
	|СГРУППИРОВАТЬ ПО
	|	Контрагенты.Ссылка
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	ВТКонтрагентыНумерация.Ссылка,
	|	ВТКонтрагентыНумерация.НомерСтроки
	|ИЗ
	|	ВТКонтрагентыНумерация КАК ВТКонтрагентыНумерация
	|ГДЕ
	|	ВТКонтрагентыНумерация.НомерСтроки = &ГенераторСЧ
	|
	|УПОРЯДОЧИТЬ ПО
	|	ВТКонтрагентыНумерация.НомерСтроки" ;
	Запрос.УстановитьПараметр("ГенераторСЧ",ЧислоСЧ);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Выборка.Следующий();
	
	Сообщить(Строка(Выборка.Ссылка) + "  НомерСтроки" +  Строка(Выборка.НомерСтроки));
...Показать Скрыть
89. Сергей (ildarovich) 4842 03.04.15 14:46 Сейчас в теме
(87) vugluscr1991, - отлично!
Нужно сказать, что такой способ я не стал пробовать из-за того, что запрос, в котором было "УПОРЯДОЧИТЬ ПО Ссылка" вернул мне явно не случайный порядок. Теперь думаю, что если сформировать справочник, генерируя ему уникальные идентификаторы подобным образом, то порядок был бы случайным. Нужно будет проверить.
Получается, что 2 (13) секунды 700 случайных элементов (пусть с повторением). А сколько всего элементов было в справочнике?
90. Andrew Schukin (Vint_1c) 15 03.04.15 14:51 Сейчас в теме
А Забыл добавить, чтобы было несколько элементов, нужно сгенерить тогда массив чисел и в запросе изменить строку | ВТКонтрагентыНумерация.НомерСтроки = &ГенераторСЧ на | ВТКонтрагентыНумерация.НомерСтроки В (&ГенераторСЧ)

Это относится к моему ответу выше.
91. Сергей (ildarovich) 4842 03.04.15 14:54 Сейчас в теме
(88) Vint_1c, тут не хорошо то, что время работы запроса для нумерации контрагентов будет квадратично зависеть от размера этого справочника. Сколько контрагентов было при экспериментах. Сколько времени работал запрос?
Чтобы проверить эту гипотезу, нужно вот этот кусок исправить так
ВЫБРАТЬ
    |    Контрагенты.Ссылка,
    |    1 КАК НомерСтроки
    |ПОМЕСТИТЬ ВТ
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты 
    |ОБЪЕДИНИТЬ ВСЕ
    |ВЫБРАТЬ
    |    Контрагенты.Ссылка,
    |    0
    |ИЗ
    |    Справочник.Контрагенты КАК Контрагенты
...Показать Скрыть
по идее, время должно вырасти примерно в четыре раза. Для больших справочников это будет существенно.
92. Andrew Schukin (Vint_1c) 15 03.04.15 15:02 Сейчас в теме
Секунд 7-8 для справочника с количеством элементов 37000.
93. Евгений Климентьев (kudlach) 5 03.04.15 15:03 Сейчас в теме
Насколько помню теорию математики для образования случайного числа - делится одно число (например 1) на простое число (например 17) . Берешь, скажем, 4 цыфру, делим ее еще раз, и так по циклу , скажем, число раз равное показателю секунд на момент начала процедуры.
в качестве знаков после запятой в цифре 0,11111 берется результат тоже начиная с какой-то цифры. Получаем показатель, который нужно умножить на количество контрагентов. Результатом будет номер контрагента.

Алгоритмов получения случайного числа много, они все неидеальны, т.к. страдают тем что нет абсолютного нормального распределения вероятности.
94. Сергей (ildarovich) 4842 03.04.15 15:23 Сейчас в теме
(92) Vint_1c, база SQL или файловая? Эксперимент по удвоению не могли бы провести?
95. Andrew Schukin (Vint_1c) 15 03.04.15 15:44 Сейчас в теме
(94) ildarovich, ,база SQL, я слегка обманул по поводу 7-8 секунд,
замеры следующие,
при первоначальном запросе было 1.5 минуты
после добавления вашего куска стало 3 минуты
Медленно, нужно подумать над этим вопросом.
96. Паша Лаптев (vugluscr1991) 6 03.04.15 16:05 Сейчас в теме
(89) ildarovich,
2902 элемента, база файловая, виртуалка
97. vtools (vtools) 69 03.04.15 16:45 Сейчас в теме
Вот такой код выдает интересный результат:
	

	Запрос=Новый Запрос;
	Запрос.Текст="ВЫБРАТЬ ПЕРВЫЕ 1
	             |	Контрагенты.Ссылка КАК Ссылка
	             |ИЗ
	             |	Справочник.Контрагенты КАК Контрагенты
	             |ГДЕ
	             |	Контрагенты.Ссылка > &Ссылка";
				 
	СлучИД=Справочники.Контрагенты.ПолучитьСсылку(Новый УникальныйИдентификатор());
	Запрос.УстановитьПараметр("Ссылка",СлучИД);
	ТЗ=Запрос.Выполнить().Выгрузить();
	ТЗ.ВыбратьСтроку();


...Показать Скрыть



Минус - значения повторяются :) Мне кажется из-за неправильного использования УникальныйИдентификатор() в качестве ГСЧ.
Если сформировать УИД самостоятельно, через обычный ГСЧ, то должно получиться (т.е. сделать обратное действие, которое описывается в ответе 14).
98. Сергей (ildarovich) 4842 03.04.15 18:21 Сейчас в теме
(96) vugluscr1991, не очень быстро для такого объема справочника. Улучшенный вариант того запроса, что описан в примере 3 в статье "Расчет хэш-функции в запросе" выдает 700 случайных элементов из справочника 15000 элементов примерно за 0,5 секунды.
Так что, если тщательно протестировать ваш метод на предмет равномерности распределения и там все будет хорошо, то его область применения - малые выборки.
99. Паша Лаптев (vugluscr1991) 6 03.04.15 20:35 Сейчас в теме
(98) ildarovich,
03.04.2015 20:31:14
Новый Запрос;
Выполнить();
03.04.2015 20:31:31
113 579 элементов в справочнике
700 случайных
Средне настроенный MS SQL на серверной платформе (аппаратное железо)
Дальнейшие тесты на платформе (умножение на 2 для случайных ссылок исключено из алгоритма 700 берем и количество уникальных смотрим):
200 000 элементов: 17 секунд 674 уникальных
66 000 элементов: 8 секунд 630 уникальных
9 000 элементов: 2 секунды 568 уникальных
1 000 элементов: менее секунды 77 уникальных
100. Сергей (ildarovich) 4842 03.04.15 21:33 Сейчас в теме
(99) vugluscr1991, спасибо за результаты. Вообще метод мне понравился тем, что для выбора одного (или нескольких) элемента он очень быстр. Но при более глубоких размышлениях обнаружил в нем серьезный "математический" дефект - он никак не обеспечивает равной вероятности выбора различных элементов справочника.
Дело в том, что вероятность выбора одного элемента будет пропорционально расстоянию до следующего элемента (если представить ссылку как большое целое число, задающее положение элемента на числовой оси). Это расстояние складывается случайным образом при формировании идентификаторов элементов справочника, но остается фиксированным при наших выборках. И может быть очень разным для разных пар соседних элементов. Если сразу за конкретным элементом расположен следующий, а после него - большое расстояние, то этот первый элемент имеет очень мало шансов быть выбранным. И если распределение сгенерированных случайно ссылок на числовой оси более - менее равномерно, то вот расстояние между соседними элементами распределено неравномерно (кажется, по закону Пуассона или близкому к нему). Так что добиться равновероятности, не распределяя ссылки равномерно (что мы сделать не можем), не получится. Поэтому правильный алгоритм, видимо, вынужден быть линейным по времени - предусматривать обработку каждой ссылки. Или опираться на готовую сплошную нумерацию элементов.
Как-то так.