Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Обычная тема Запрос с фильтром по "категории" контрагента/товара (число прочтений - 3244 )
mc
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 59
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Запрос с фильтром по "категории" контрагента/товара
02. Декабря 2010 :: 13:52
Печать  
Просто получение категории было здесь http://www.1cpp.ru/forum/YaBB.pl?num=1290435272

Усложняем задачу
В стандартных конфигах для Украины есть спр.КатегорииКонтрагентов подчинен спр.Контрагенты.
В карточке контрагента может быть пусто или 1 или несколько категорий.
То же и для спр.Товары/ТМЦ.

Стандартные отчеты позволяют отбирать одиночный или множественный фильтр.
Во множественном фильтре есть доп. функция "одна из" категория или "одновременно все".

Вот чудо код в отчете
Код
Выбрать все
	Если глФильтрПоСправочнику("Контрагенты",
						),
						СписокПокупателей,
						ТекстЗапроса,Заг,Язык,
						ателям,покупцю,покупцях")=0 Тогда
		Возврат;
	КонецЕсли;
 



а вот код фунции из глобальника
Код
Выбрать все
// ===============================
// Отбирает товары или контрагентов в соответствии с фильтрами по их категориям.
// Если ВидСправочника - вид справочника, из которого отбираются позиции
// Отбирает все позиции номенклатуры или контрагентов такие, что:
//		- если Категория.Выбран()>0, то у позиция принадлежит категории "Категория"
//		- если МФКатегории.РазмерСписка()>0, то
//			а)	если ТипМФКатегории=1, то позиция принадлежит одной из категорий из списка "МФКатегории"
//			б)  если ТипМФКатегории=2, то позиция принадлежит сразу всем категориям из списка "МФКатегории"
// Помещает список отобранных позиций в список значений "Результат" и формирует заголовок для отчета "Заголовок"
Процедура ,Результат,ЗаголовокРус,ЗаголовокУкр) Экспорт
	Перем НазвСправочникаКатегорий;
	Перем ТекстЗапроса, Запрос;
	Перем ЧислоКатегорийВСписке,ЧислоКатегорий;
	Перем ПозицияСправочника;                          
	Перем ЕстьМножественныйФильтр;
	ЕстьМножественныйФильтр=0;
	Если ТипМФКатегории>0 Тогда
		Если МФКатегории.РазмерСписка()>0 Тогда
			ЕстьМножественныйФильтр=1;
		КонецЕсли;
	КонецЕсли;
	НазвСправочникаКатегорий = ?(ВРег(ВидСправочника)="ТМЦ","КатегорииТоваров",
								?(ВРег(ВидСправочника)="КОНТРАГЕНТЫ","КатегорииКонтрагентов",
									"КатегорииКонтрагентов"));
	Результат.УдалитьВсе();
	Заголовок = "";
	Если (Категория.Выбран()>0)ИЛИ(ЕстьМножественныйФильтр=1) Тогда

		ТекстЗапроса = "      
		    |Обрабатывать НеПомеченныеНаУдаление;
			|КатегорияПозиции = Справочник."+НазвСправочникаКатегорий+".ТекущийЭлемент;
			|Позиция = Справочник."+НазвСправочникаКатегорий+".Владелец;
			|КатегорияПоз = Справочник."+НазвСправочникаКатегорий+".Категория;                
			|Группировка Позиция Без Групп;
			|";                          

		Если (ЕстьМножественныйФильтр=1)И(ТипМФКатегории=2) Тогда
			// одновременно все категории должны быть в списке ТипМФКатегории
			ТекстЗапроса = ТекстЗапроса + "Группировка КатегорияПоз Без Групп;";
		КонецЕсли;
		Если (Категория.Выбран()>0) Тогда
   			ТекстЗапроса = ТекстЗапроса + "Условие (КатегорияПоз в Категория);";
   			ЗаголовокРус = ЗаголовокРус + " из категории """+ СокрЛП(Категория.Наименование)+"""";
   			ЗаголовокУкр = ЗаголовокУкр + " із категорії """+ СокрЛП(Категория.Наименование)+"""";
		КонецЕсли;
		Если (ЕстьМножественныйФильтр=1) Тогда
			ТекстЗапроса = ТекстЗапроса + "Условие (КатегорияПоз в МФКатегории);";	      
			Если ТипМФКатегории=1 Тогда
				ЗаголовокРус = ЗаголовокРус + " из одной из категорий: "+МФКатегории.ВСтрокуСРазделителями();
				ЗаголовокУкр = ЗаголовокУкр + " із однієї з категорій: "+МФКатегории.ВСтрокуСРазделителями();
			ИначеЕсли ТипМФКатегории=2 Тогда	                                                      
				ЗаголовокРус = ЗаголовокРус + " одновременно из категорий: "+МФКатегории.ВСтрокуСРазделителями();
				ЗаголовокУкр = ЗаголовокУкр + " одночасно із категорій: "+МФКатегории.ВСтрокуСРазделителями();
			КонецЕсли;
		КонецЕсли;
		// выполняем запрос
		Запрос = СоздатьОбъект("Запрос");
		Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда
			Возврат;
		КонецЕсли;
		Если ЕстьМножественныйФильтр=1 Тогда
			ЧислоКатегорийВСписке = МФКатегории.РазмерСписка();
		КонецЕсли;
		// выгружаем все отобранные товары в список
		Запрос.ВНачалоВыборки();
		Пока Запрос.Группировка("Позиция")>0 Цикл
			Если Запрос.Позиция.Выбран()=1 Тогда                                  
				Если (ЕстьМножественныйФильтр=1)И(ТипМФКатегории=2) Тогда
					// одновременно все категории должны быть в списке МФКатегории
					ПозицияСправочника = Запрос.Позиция.ТекущийЭлемент();
					// ячитаем число категорий
					ЧислоКатегорий = 0;
					Пока Запрос.Группировка("КатегорияПоз")>0 Цикл
						Если Запрос.КатегорияПоз.Выбран()=1 Тогда                                  
							ЧислоКатегорий = ЧислоКатегорий + 1;
						КонецЕсли;
					КонецЦикла;
					// все категории будут тогда и только тогда, когда число отобранных
					// категорий будет не меньше размера списка МФКатегории
					Если ЧислоКатегорий>=ЧислоКатегорийВСписке Тогда
						Результат.ДобавитьЗначение(ПозицияСправочника.ТекущийЭлемент());
					КонецЕсли;
				Иначе
					Результат.ДобавитьЗначение(Запрос.Позиция.ТекущийЭлемент());
				КонецЕсли;
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
КонецПроцедуры 



То есть перебирается весь спр.Контрагенты на соответсвие фильтрам.

Теперь вопрос: как сие чудо переложить на скл-запрос?
  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Запрос с фильтром по "категории" контрагента/товара
Ответ #1 - 06. Декабря 2010 :: 07:48
Печать  
Примерно так:
Код
Выбрать все
// ===============================
// Отбирает товары или контрагентов в соответствии с фильтрами по их категориям.
// Если ВидСправочника - вид справочника, из которого отбираются позиции
// Отбирает все позиции номенклатуры или контрагентов такие, что:
//		- если Категория.Выбран()>0, то у позиция принадлежит категории "Категория"
//		- если МФКатегории.РазмерСписка()>0, то
//			а)	если ТипМФКатегории=1, то позиция принадлежит одной из категорий из списка "МФКатегории"
//			б)  если ТипМФКатегории=2, то позиция принадлежит сразу всем категориям из списка "МФКатегории"
// Помещает список отобранных позиций в список значений "Результат" и формирует заголовок для отчета "Заголовок"
Процедура ,Результат,ЗаголовокРус,ЗаголовокУкр) Экспорт
	ЕстьМножественныйФильтр=0;
	Если ТипМФКатегории > 0 Тогда
		Если МФКатегории.РазмерСписка()>0 Тогда
			ЕстьМножественныйФильтр=1;
		КонецЕсли;
	КонецЕсли;
	НазвСправочникаКатегорий = ?(ВРег(ВидСправочника)="ТМЦ","КатегорииТоваров",
								?(ВРег(ВидСправочника)="КОНТРАГЕНТЫ","КатегорииКонтрагентов",
									"КатегорииКонтрагентов"));
	Результат.УдалитьВсе();
	Заголовок = "";
	Если (Категория.Выбран()>0)ИЛИ(ЕстьМножественныйФильтр=1) Тогда
		база = СоздатьОбъект("SqliteBase");
		база.Открыть(":memory:");
		Запрос = база.НовыйЗапрос();
		Если (ЕстьМножественныйФильтр = 1) И (ТипМФКатегории = 2) Тогда
			ТекстЗапроса = "select
			|т.Элемент [Элемент :Справочник." + ВидСправочника +"]
			|from (
			|	select р.Элемент, count(*)
			|	from (
			|	select distinct
			|	Кат.parentext Элемент,
			|	Кат.Категория
			|";
		Иначе
			ТекстЗапроса = "select distinct
			|Кат.parentext [Элемент :Справочник." + ВидСправочника +"]";
		КонецЕсли;
		ТекстЗапроса = ТекстЗапроса + "
		|from [Справочник." + НазвСправочникаКатегорий +"] Кат
		|where Кат.ismark<>'*'
		|";

		Если (Категория.Выбран()>0) Тогда
			Запрос.Подставлять(":выбКатегория", Категория);
 			  ТекстЗапроса = ТекстЗапроса + "and Кат.Категория = :выбКатегория
 			  |";
 			  ЗаголовокРус = ЗаголовокРус + " из категории """+ СокрЛП(Категория.Наименование)+"""";
 			  ЗаголовокУкр = ЗаголовокУкр + " із категорії """+ СокрЛП(Категория.Наименование)+"""";
		КонецЕсли;

		Если (ЕстьМножественныйФильтр=1) Тогда
			база.УложитьОбъекты(МФКатегории, "МФКатегории");
			ТекстЗапроса = ТекстЗапроса + "and Кат.Категория in (select val from МФКатегории)
			|";
			Если ТипМФКатегории=1 Тогда
				ЗаголовокРус = ЗаголовокРус + " из одной из категорий: "+МФКатегории.ВСтрокуСРазделителями();
				ЗаголовокУкр = ЗаголовокУкр + " із однієї з категорій: "+МФКатегории.ВСтрокуСРазделителями();
			ИначеЕсли ТипМФКатегории=2 Тогда
				ЗаголовокРус = ЗаголовокРус + " одновременно из категорий: "+МФКатегории.ВСтрокуСРазделителями();
				ЗаголовокУкр = ЗаголовокУкр + " одночасно із категорій: "+МФКатегории.ВСтрокуСРазделителями();
				ТекстЗапроса = ТекстЗапроса + ") р
				|group by р.Элемент
				|having count(*) >= :ЧислоКатегорий) т";
				Запрос.Подставлять(":ЧислоКатегорий", МФКатегории.РазмерСписка());
			КонецЕсли;
		КонецЕсли;
		Запрос.ВыполнитьЗапрос(ТекстЗапроса, Результат);
	КонецЕсли;
КонецПроцедуры
 

  
Наверх
 
IP записан
 
orefkov
1c++ developer
1c++ moderator
Отсутствует


I Love YaBB 2!

Сообщений: 896
Зарегистрирован: 20. Мая 2006
Re: Запрос с фильтром по "категории" контрагента/товара
Ответ #2 - 06. Декабря 2010 :: 07:58
Печать  
mc писал(а) 02. Декабря 2010 :: 13:52:
То есть перебирается весь спр.Контрагенты на соответсвие фильтрам.

Это утверждение не верно.
И не указано, база дбф или sql
  
Наверх
 
IP записан
 
mc
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 59
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Запрос с фильтром по "категории" контрагента/товара
Ответ #3 - 06. Декабря 2010 :: 10:51
Печать  
спасибо! почти так себе и представлял!
база sql
ну почти весь справочник перебирается  Круглые глаза
  
Наверх
 
IP записан
 
mc
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 59
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Запрос с фильтром по "категории" контрагента/товара
Ответ #4 - 07. Декабря 2010 :: 14:55
Печать  
orefkov
попытался адаптировать ваш код для простой выборки при отборе "одновременно все"

Код
Выбрать все
		|SELECT
		|	табТ.Элемент
		|FROM (
		|	SELECT
		|		табР.Элемент,
		|	 COUNT(*)
		|	FROM (
		|		SELECT DISTINCT
		|			СпрКатегорииКонтрагентов.ParentExt AS Элемент,
		|			$СпрКатегорииКонтрагентов.Категория AS [Категория $Справочник.ВидыКатегории]
		|		FROM $Справочник.КатегорииКонтрагентов AS СпрКатегорииКонтрагентов
		|		WHERE (СпрКатегорииКонтрагентов.IsMark = 0) AND ($СпрКатегорииКонтрагентов.Категория IN (SELECT VAL FROM #МФКатегории))
		|	) табР
		|	GROUP BY табР.Элемент
		|	HAVING COUNT(*) >= :ЧислоКатегорий
		|) табТ

	RS.УложитьСписокОбъектов(МФКатКонтрагентов, "#МФКатегории");
	моЗапрос.УстановитьТекстовыйПараметр("ЧислоКатегорий", МФКатКонтрагентов.РазмерСписка()); 



при выполнении выдает слеющую ошибку
ЗапросSQL::ВыполнитьSQL(Число Отладка=0, Число ТаблицаГруппировок=0) : State 42000, native 8155, message [Microsoft][ODBC SQL Server Driver][SQL Server]No column was specified for column 2 of 'табТ'.
ТЗ = RS.ВыполнитьИнструкцию(Текст);
{H:\Фактор\1C-SQL\1C++\Classes\ЗапросSQL.ert(126) }

оТЗ = моЗапрос.Выполнить(0, 0);
{L:\RECOVERYG\EXT\EXT_FACTOR\TEST_КОНТРАГЕНТ_КАТЕГОРИЯ.ERT(131)}: ЗапросSQL::ВыполнитьSQL(Число Отладка=0, Число ТаблицаГруппировок=0) : State 42000, native 8155, message [Microsoft][ODBC SQL Server Driver][SQL Server]No column was specified for column 2 of 'табТ'.
ТЗ = RS.ВыполнитьИнструкцию(Текст);
{H:\Фактор\1C-SQL\1C++\Classes\ЗапросSQL.ert(126) }


помогите найти ошибку


для отбора "один из" код работает
Код
Выбрать все
		|SELECT DISTINCT
		|	СпрКатегорииКонтрагентов.ParentExt AS [Контрагенты $Справочник.Контрагенты],
		|	$СпрКатегорииКонтрагентов.Категория AS [Категория $Справочник.ВидыКатегории]
		|FROM $Справочник.КатегорииКонтрагентов AS СпрКатегорииКонтрагентов
		|WHERE (СпрКатегорииКонтрагентов.IsMark = 0) AND ($СпрКатегорииКонтрагентов.Категория IN (SELECT VAL FROM #МФКатегории))
		|
 

  
Наверх
 
IP записан
 
Z1
God Member
*****
Отсутствует


I Love YaBB 2!

Сообщений: 2906
Местоположение: Москва
Зарегистрирован: 26. Мая 2006
Пол: Мужской
Re: Запрос с фильтром по "категории" контрагента/товара
Ответ #5 - 07. Декабря 2010 :: 15:03
Печать  
либо попробуй убрать самый внешний select
либо ) табТ замени на ) as табТ
  
Наверх
 
IP записан
 
mc
Junior Member
**
Отсутствует


I Love YaBB 2!

Сообщений: 59
Зарегистрирован: 24. Мая 2006
Пол: Мужской
Re: Запрос с фильтром по "категории" контрагента/товара
Ответ #6 - 07. Декабря 2010 :: 15:13
Печать  
Z1
Цитата:
либо ) табТ замени на ) as табТ

не помогло

а вот это
Цитата:
либо попробуй убрать самый внешний select

помогло
Код
Выбрать все
		|	SELECT
		|		табР.Элемент AS [Контрагенты $Справочник.Контрагенты],
		|	 COUNT(*) AS КвоСовпадений
		|	FROM (
		|		SELECT DISTINCT
		|			СпрКатегорииКонтрагентов.ParentExt AS Элемент,
		|			$СпрКатегорииКонтрагентов.Категория AS [Категория $Справочник.ВидыКатегории]
		|		FROM $Справочник.КатегорииКонтрагентов AS СпрКатегорииКонтрагентов
		|		WHERE (СпрКатегорииКонтрагентов.IsMark = 0) AND ($СпрКатегорииКонтрагентов.Категория IN (SELECT VAL FROM #МФКатегории))
		|	) табР
		|	GROUP BY табР.Элемент
		|	HAVING COUNT(*) >= :ЧислоКатегорий 



ВСЕМ БОЛЬШОЕ СПАСИБО!!!
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать