Переключение на Главную Страницу Страницы: 1 ОтправитьПечать
Горячая тема (более 10 ответов) Временные таблицы, теперь ДБФ. (число прочтений - 12477 )
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Временные таблицы, теперь ДБФ.
01. Сентября 2007 :: 19:01
Печать  
Простейший код создания временной таблицы
Код
Выбрать все
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('SELECT  * INTO CURSOR  TmpTable NOFILTER from sc33 as WW ')");

ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("Select *  from TmpTable ");
 

  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #1 - 01. Сентября 2007 :: 19:03
Печать  
Сложный (общий случай)

Функция
Код
Выбрать все
Функция ов=0,Опции="CURSOR NOFILTER") Экспорт
// Опции="ARRAY" временная таблица в оперативной памяти

// Опции="CURSOR NOFILTER" временная таблица , только чтение,read-only, во временных файлах ? (не нашел)
// один индекс

// Опции="CURSOR READWRITE" временная таблица , можно добавлять записи (WRITE), во временных файлах ?
// (не нашел)     несколько индексов

// Опции="TABLE" прямая запись в таблицу. В целях избежать случайной порчи данных здесь не использую :)
//...

// По сообщению с форума sql.ru на вопрос о разнице между CURSOR и ARRAY
// FoxPro стремится все разместить в памяти (курсор). И если таблица очень маленькая то разницы между
//массивом и таблицей в Вашем случае нет...
	ОлеДБКоманда = глОлеДБ.СоздатьКоманду();

	// ....
	МД = СоздатьОбъект("MetaDataWork");  
	Если  ПустоеЗначение(СписокТекстовыхПараметров)=0 Тогда
		Для Счетчик=1 По СписокТекстовыхПараметров.РазмерСписка() Цикл
			ТекПредставление="";
			;
			МД.УстановитьТекстовыйПараметр(ТекПредставление,ТекЗначение);
		КонецЦикла;
	КонецЕсли;
	ПодзапросSQL=МД.ОбрМетаСКЛ(ТекстЗапроса);

//	ВрТекстЗапроса=ПодзапросSQL;
	// Знак "'" не  поддерживается, поэтому заменяем на скобки
	Скобка="[";
	номпозиции=Найти(ПодзапросSQL,"'");
	Пока номпозиции<>0 Цикл  
		1);
		Если Скобка="[" Тогда   Скобка="]"
		Иначе  Скобка="["
		КонецЕсли;
		номпозиции=Найти(ПодзапросSQL,"'");
	КонецЦикла;


	//Разделитель строк не поддерживается поэтому убираем,
	//строки больше 255 симолов не поддерживаются , поэтому удлиняем при помощи CHR(13)
    ВрТекстЗапроса="";
	Для Счетчик=1 По СтрКоличествоСтрок(ПодзапросSQL) Цикл
		ТекСтрока=СтрПолучитьСтроку(ПодзапросSQL,Счетчик);
	//	Сообщить(ТекСтрока);
		ТекСтрока=" "+СокрЛП(ТекСтрока)+" ";
		Если Счетчик=1 Тогда
			ВрТекстЗапроса=ВрТекстЗапроса+ТекСтрока;
		Иначе  
			Если СокрЛП(ТекСтрока)<>"" Тогда
			ПереносСтрокиФоксПро="'+"+CHR(13)+"'";
			ВрТекстЗапроса=ВрТекстЗапроса+ПереносСтрокиФоксПро+ТекСтрока;
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
//	Сообщить(ВрТекстЗапроса);
	//Даты с "'" и с "[" не поддерживаются
	номпозиции=Найти(ВрТекстЗапроса,"{d"); // {d [2006-01-01]}
	Пока  номпозиции<>0 Цикл

			Начало=Лев(ВрТекстЗапроса,номпозиции-1);
			ДатаПар=Сред(ВрТекстЗапроса,номпозиции+4,10);
			Конец=Сред(ВрТекстЗапроса,номпозиции+16);

			ВрТекстЗапроса=Начало+"{^ "+ДатаПар+"}"+Конец;
			номпозиции=Найти(ВрТекстЗапроса,"{d");
	КонецЦикла;

//	Сообщить(ВрТекстЗапроса);  
    Если Опции="ARRAY" Тогда
		ТипТабл="ARRAY"; ДобПар="";
    ИначеЕсли  Опции="CURSOR NOFILTER" Тогда
	   ТипТабл="CURSOR"; ДобПар="NOFILTER";
	Иначе	//  CURSOR READWRITE
		 ТипТабл="CURSOR"; ДобПар="READWRITE";
	КонецЕсли;

    ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('SELECT  * INTO "+ТипТабл+"  "+
			ИмяВременнойТаблицы+" "+ДобПар+" from ("+ВрТекстЗапроса+ ")as WW  ')");
	ОлеДБКоманда.Закрыть();
	Возврат ТЗ.ПолучитьЗначение(1,"return_value");
КонецФункции  

« Последняя редакция: 11. Февраля 2008 :: 14:07 - kiruha »  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #2 - 01. Сентября 2007 :: 19:07
Печать  
Пример вызова
Код
Выбрать все
ОлеДБКоманда = глОлеДБ.СоздатьКоманду();
 ТекстЗапроса="  SELECT
	|		$РегОстатков.Товар as  Товар
	|		FROM
	|			$РегистрИтоги.ОстаткиТоваров as РегОстатков
	|		WHERE
	|			РегОстатков.PERIOD =:ДатаПериодаОстатков~~ ";

	СписокТекстовыхПараметров=СоздатьОбъект("СписокЗначений");
	СписокТекстовыхПараметров.Установить("ДатаПериодаОстатков",'01.01.2006');
	глОлеДБ= СоздатьОбъект("OLEDBData");
//..здесь соединение
	в);

	ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("Select *  from TmpTable ");
	ОлеДБКоманда.Закрыть(); 

  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #3 - 01. Сентября 2007 :: 19:19
Печать  
P.S. Временная таблица будет сохранена, пока не разорвана ссесия,
поэтому ее желательно уничтожать.

Код
Выбрать все
ОлеДБКоманда.Выполнить("EXECSCRIPT('USE IN TmpTable ')"); 

« Последняя редакция: 11. Февраля 2008 :: 14:05 - kiruha »  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #4 - 01. Сентября 2007 :: 20:16
Печать  
Пример3. Аналог WITH ROLLUP
Временная таблица
Код
Выбрать все
SELECT
	|		$РегОстатков.Склад as  Склад,
	|		$РегОстатков.Товар as  Товар,
	|		SUM($РегОстатков.ОстатокТовара) as  ОстатокТовара
	|		FROM
	|			$РегистрИтоги.ОстаткиТоваров as РегОстатков
	|		WHERE
	|			РегОстатков.PERIOD =:ДатаПериодаОстатков~~
	|	 GROUP BY $РегОстатков.Склад,$РегОстатков.Товар  



Результат
Код
Выбрать все
| Select
	|TmpTable.Склад as Склад,
	|'AAAAAAAAA' as Товар,
	|000000000001.00 as Grouping,
	|SUM(TmpTable.ОстатокТовара) as  ОстатокТовара
	|  from TmpTable
	|GROUP BY Склад,Товар,Grouping
	|
	|UNION ALL
	|
	| Select
	|TmpTable.Склад ,
	|TmpTable.Товар ,
	|000000000002.00 ,
	|TmpTable.ОстатокТовара
	|  from TmpTable 


Сортировку и приведение типов тривиально, поэтому не привожу
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #5 - 01. Сентября 2007 :: 20:28
Печать  
Еще возможно :

Пример 4. Уложить список объектов.
Тривиально

Пример 5. Все и Все вошедшие в запрос.
Через Distinct к временной таблице и декартово произведение.
Довольно большая нагрузка при декартовом произведении на сетку, поэтому целесообразно во
временные таблицы на клиенте и только потом произведение.

Пример 6.
Вычисления (как планировалось через sqlite ) - наверно возможно, но нужна быстрая выгрузка из ТЗ во временную
таблицу на уровне ядра...
Можно конечно добавлять записи в цикле (для CURSOR READWRITE)
Код
Выбрать все
ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('INSERT INTO TmpTable (ID )   VALUES (["+ID+"])')"); 


Но данный код выполняется настолько долго , что теряется смысл оптимизации
(просто Выполнить() не спасает...)
« Последняя редакция: 03. Сентября 2007 :: 12:29 - kiruha »  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #6 - 01. Сентября 2007 :: 21:24
Печать  
Пример 7
Создание индексов для временной таблицы для оптимизации вычислений
Код
Выбрать все
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('SELECT  WW.ID INTO CURSOR  TmpTable NOFILTER from sc33 as WW  ')");
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('INDEX ON TmpTable.ID TAG ID ')"); 


Создан индекс ID

Пример 8.
Перенумерация для временной таблицы.
Код
Выбрать все
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('SELECT  WW.ID,RECNO() as Номер INTO CURSOR  TmpTable NOFILTER from sc33 as WW  ')");
// Оптимизируем таблицу для выборки по номеру :
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('INDEX ON TmpTable.Номер TAG Номер ')"); 



Пример 9.
Удаление записей (освобождение памяти)
Код
Выбрать все
ОлеДБКоманда.ВыполнитьИнструкцию("DELETE  from TmpTable"); 

« Последняя редакция: 03. Сентября 2007 :: 12:31 - kiruha »  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #7 - 03. Сентября 2007 :: 18:08
Печать  
Переменные памяти.
Код
Выбрать все
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('PUBLIC МояПеременная')");
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('STORE [  1YWY   ] TO МояПеременная')"); 



В первой строке объявили переменную памяти.
Во второй задали значение '  1YWY   ' (это ID документа)

Теперь эту переменную можно использовать
Код
Выбрать все
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("Select *  from TmpTable where TmpTable.IDDOC=МояПеременная"); 



Создание временной таблицы в памяти
Код
Выбрать все
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('CREATE CURSOR TmpTable (МойСтолбец Character(9) NOT NULL) ')");
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('PUBLIC МояПеременная')");
ТЗ = ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('STORE [  1YWY   ] TO МояПеременная')");

ОлеДБКоманда.ВыполнитьИнструкцию("EXECSCRIPT('INSERT INTO TmpTable (МойСтолбец)   VALUES(МояПеременная)')");  


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


I Love YaBB 2!

Сообщений: 313
Зарегистрирован: 24. Декабря 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #8 - 01. Февраля 2009 :: 21:14
Печать  
kiruha писал(а) 01. Сентября 2007 :: 20:28:
Еще возможно :

Пример 4. Уложить список объектов.
Тривиально


можно пример плз.
  
Наверх
 
IP записан
 
kiruha
1c++ power user
Отсутствует



Сообщений: 1249
Зарегистрирован: 11. Апреля 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #9 - 02. Февраля 2009 :: 08:12
Печать  
kriblya писал(а) 01. Февраля 2009 :: 21:14:
kiruha писал(а) 01. Сентября 2007 :: 20:28:
Еще возможно :

Пример 4. Уложить список объектов.
Тривиально


можно пример плз.



Тривиально имеется ввиду уложить простые типы
создаем таблицу
Цитата:
ТЗ = ОлеДБКоманда.Выполнить("EXEC('CREATECURSOR TmpTable (МойСтолбец Character(9) NOT NULL) ')");

И в цикле пихаем список
Цитата:
ОлеДБКоманда.Выполнить("NSERT INTO TmpTable (МойСтолбец)   VALUES(МояПеременная");  
- параметрически или непараметрически - до 100 элементов это неважно.
Укладывать можно хоть числа, хоть даты, хоть строки любой длины и т.д - в отличии от стандартного метода.
Когда таблица не нужна ее уничтожают
Цитата:
     ОлеДБКоманда.Выполнить("EXEC('USE IN TmpTable  ')");

Или она уничтожается автомат, при разрыве ссесии

Более сложный случай укладки справочника с элементами групп списка.
  
Наверх
 
IP записан
 
kriblya
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 313
Зарегистрирован: 24. Декабря 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #10 - 02. Февраля 2009 :: 08:51
Печать  
Цитата:
Более сложный случай укладки справочника с элементами групп списка.

оно то и интересует..., а то в выполнении запросов это одно из самых тонких мест
  
Наверх
 
IP записан
 
Chieftain
Senior Member
****
Отсутствует


___

Сообщений: 498
Местоположение: Тула
Зарегистрирован: 15. Февраля 2007
Пол: Мужской
Re: Временные таблицы, теперь ДБФ.
Ответ #11 - 02. Февраля 2009 :: 11:34
Печать  
kriblya писал(а) 02. Февраля 2009 :: 08:51:
Цитата:
Более сложный случай укладки справочника с элементами групп списка.

оно то и интересует..., а то в выполнении запросов это одно из самых тонких мест

Я что-то типа такого писал, вроде достаточно быстро работало
Код
Выбрать все
	  ФильтрТоваров	  = "";
	  Для Ном=1 По СписокНоменклатуры.РазмерСписка() Цикл
		    ФильтрТоваров    = окНоменклатуры.ПолучитьЗначение(ном))+"'";
	  КонецЦикла;

	  Запрос.Выполнить("EXECSCRIPT('CREATE CURSOR NomList(ID Character(9))')");
	  Запрос.ВыполнитьИнструкцию("INSERT INTO NomList
		    |SELECT спр.ID
		    |FROM	$Справочник.Номенклатура as спр
		    |LEFT JOIN $Справочник.Номенклатура as спр1 on (спр1.ID=спр.ParentID)
		    |LEFT JOIN $Справочник.Номенклатура as спр2 on (спр2.ID=спр1.ParentID)
		    |LEFT JOIN $Справочник.Номенклатура as спр3 on (спр3.ID=спр2.ParentID)
		    |LEFT JOIN $Справочник.Номенклатура as спр4 on (спр4.ID=спр3.ParentID)
		    |LEFT JOIN $Справочник.Номенклатура as спр5 on (спр5.ID=спр4.ParentID)
		    |WHERE (спр.IsFolder=2)AND(
		    |(спр.ID in("+ФильтрТоваров+"))or
		    |(спр1.ID in("+ФильтрТоваров+"))or
		    |(спр2.ID in("+ФильтрТоваров+"))or
		    |(спр3.ID in("+ФильтрТоваров+"))or
		    |(спр4.ID in("+ФильтрТоваров+"))or
		    |(спр5.ID in("+ФильтрТоваров+"))
		    |)"); 

  
Наверх
ICQ  
IP записан
 
kriblya
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 313
Зарегистрирован: 24. Декабря 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #12 - 02. Февраля 2009 :: 20:37
Печать  
а  такая конструкция работает быстрее, чем уложить список объектов?
зы как я понял это справочник с 5 уровнями иерархии...

сорри по id уже в оптиме
  
Наверх
 
IP записан
 
Chieftain
Senior Member
****
Отсутствует


___

Сообщений: 498
Местоположение: Тула
Зарегистрирован: 15. Февраля 2007
Пол: Мужской
Re: Временные таблицы, теперь ДБФ.
Ответ #13 - 02. Февраля 2009 :: 21:09
Печать  
kriblya писал(а) 02. Февраля 2009 :: 20:37:
а  такая конструкция работает быстрее, чем уложить список объектов?
зы как я понял это справочник с 5 уровнями иерархии...

ага, 5 уровней
на скорость глобально не тестил, но должно быть быстрее чем сбор элементов+укладка.
да и фильтры у меня не просто на вхождение, условий может целая куча накладываться, одним запросом как минимум удобнее
  
Наверх
ICQ  
IP записан
 
kriblya
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 313
Зарегистрирован: 24. Декабря 2007
Re: Временные таблицы, теперь ДБФ.
Ответ #14 - 02. Февраля 2009 :: 21:19
Печать  
ну джоин точно в индекс ставить надо. скорость увеличишь точно...
уже в оптиме....
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: 1
ОтправитьПечать