Переключение на Главную Страницу Страницы: 1 ... 21 22 [23] 24 25 ... 60 ОтправитьПечать
Очень популярная тема (более 25 ответов) Класс "ПрямойЗапрос" (число прочтений - 304813 )
anko
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 9
Зарегистрирован: 11. Ноября 2009
Re: Класс "ПрямойЗапрос"
Ответ #330 - 18. Ноября 2009 :: 11:17
Печать  
Подскажите пожалуйста
Пробую использовать прямой запрос
подзадача: надо выбрать значения основного свойства номенклатуры
Запрос такой:
Код
Выбрать все
ТекстЗапроса = "ВЫБРАТЬ
$Номенклатура.ТекущийЭлемент КАК [Номенклатура $Справочник.Номенклатура]
|, $Свойства.ТекущийЭлемент КАК [Свойство $Справочник.СвойстваНоменклатуры]
|, $Свойства.ЗначениеСвойства КАК [Бренд $Справочник.ЗначенияСвойств]
|ИЗ Справочник.СвойстваНоменклатуры КАК Свойства
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура  КАК Номенклатура По $Номенклатура.ОсновноеСвойство = $Свойства.ТекущийЭлемент";
 


Запрос выполняется очень долго, видимо потому, что не попадает в индекс
Наоборот тоже пробовал, без разницы
Подскажите варианты
  
Наверх
 
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #331 - 18. Ноября 2009 :: 13:46
Печать  
Вот так напиши... если я правильно задачу понял...

Код
Выбрать все
"ВЫБРАТЬ
|	$Номенклатура.ТекущийЭлемент КАК [Номенклатура $Справочник.Номенклатура]
|	,$Свойства.ТекущийЭлемент КАК [Свойство $Справочник.СвойстваНоменклатуры]
|	,$Свойства.ЗначениеСвойства КАК [Бренд $Справочник.ЗначенияСвойств]
|ИЗ Справочник.Номенклатура КАК Номенклатура $nolock //(не забывай об этом)
|ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СвойстваНоменклатуры КАК Свойства $nolock
|ПО $Номенклатура.ОсновноеСвойство = $Свойства.ТекущийЭлемент" 


И не по возможности покажи сообщение с РежимОтладки = 1.
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
anko
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 9
Зарегистрирован: 11. Ноября 2009
Re: Класс "ПрямойЗапрос"
Ответ #332 - 18. Ноября 2009 :: 14:02
Печать  
с ЛЕВОЕ СОЕДИНЕНИЕ все нормально
интересно, почему с "внутреннее" не работает
сообщение отладки (пришлось поставить ПЕРВЫЕ 5, а то зависало намертво)
Код
Выбрать все
SELECT
Номенклатура.ID AS [Номенклатура $Справочник.Номенклатура]
, Свойства.ID AS [Свойство $Справочник.СвойстваНоменклатуры]
, Свойства.ЗначениеСвойства AS [Бренд $Справочник.ЗначенияСвойств]
FROM Справочник_Номенклатура  AS Номенклатура
INNER JOIN Справочник_СвойстваНоменклатуры AS Свойства ON Номенклатура.ОсновноеСвойство = Свойства.ID
 LIMIT 5
Подбор индекса для таблицы SC84:
	Ограничения:
	В кэше не найдено
	Индекс не выбран.
	Стоимость: 9984
Подбор индекса для таблицы SC562:
	Ограничения:
	В кэше не найдено
	Индекс не выбран.
	Стоимость: 9982
Подбор индекса для таблицы SC84:
	Ограничения: SP4427[ОсновноеСвойство]=;
	В кэше не найдено
	Индекс не выбран.
	Стоимость: 9984
Время подготовки запроса: 20 мс, время выполнения запроса: 471 мс. 

  
Наверх
 
IP записан
 
anko
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 9
Зарегистрирован: 11. Ноября 2009
Re: Класс "ПрямойЗапрос"
Ответ #333 - 18. Ноября 2009 :: 14:14
Печать  
и еще можно вопрос:
пишу так:
Код
Выбрать все
ВЫБРАТЬ
Товар.Номенклатура, Бренд.ЦенаПоставщика, Бренд.Приоритет
ИЗ
(ВЫБРАТЬ
$Номенклатура.ТекущийЭлемент КАК [Номенклатура $Справочник.Номенклатура]
, $Свойства.ТекущийЭлемент КАК [Свойство $Справочник.СвойстваНоменклатуры]
, $Свойства.ЗначениеСвойства КАК [Бренд $Справочник.ЗначенияСвойств]
ИЗ Справочник.Номенклатура  КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СвойстваНоменклатуры КАК Свойства По $Номенклатура.ОсновноеСвойство = $Свойства.ТекущийЭлемент
) КАК Товар

ВНУТРЕННЕЕ СОЕДИНЕНИЕ
(ВЫБРАТЬ                                    
  $ДокШапка.Бренд КАК  [Бренд $Справочник.ЗначенияСвойств]
, $ДокСтроки.ЦенаПоставщика КАК [Цена $Справочник.ТипыЦен]
, $ДокСтроки.Наценка КАК [Наценка $Число]
, $ДокСтроки.Приоритет КАК [Приоритет $Число]
ИЗ ДокументСтроки.ПравилоФормированияЦен КАК ДокСтроки $nolock
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.ПравилоФормированияЦен ДокШапка $nolock По $ДокСтроки.ТекущийДокумент = $ДокШапка.ТекущийДокумент
ГДЕ
$ДокСтроки.СвояЦена = :ТипЦен
И $ДокСтроки.Вкл <> 0) КАК Правила
По Правила.Бренд = Номенклатура.Бренд 


[/code]
получаю в ответ:
Код
Выбрать все
SELECT
Товар.Номенклатура, Бренд.ЦенаПоставщика, Бренд.Приоритет
FROM
(SELECT
Номенклатура.ID AS [Номенклатура $Справочник.Номенклатура]
, Свойства.ID AS [Свойство $Справочник.СвойстваНоменклатуры]
, Свойства.ЗначениеСвойства AS [Бренд $Справочник.ЗначенияСвойств]
FROM Справочник_Номенклатура  AS Номенклатура
LEFT JOIN Справочник_СвойстваНоменклатуры AS Свойства ON Номенклатура.ОсновноеСвойство = Свойства.ID
) AS Товар

INNER JOIN
(SELECT                                    
  ДокШапка.Бренд AS  [Бренд $Справочник.ЗначенияСвойств]
, ДокСтроки.ЦенаПоставщика AS [Цена $Справочник.ТипыЦен]
, ДокСтроки.Наценка AS [Наценка $Число]
, ДокСтроки.Приоритет AS [Приоритет $Число]
FROM ДокументСтроки_ПравилоФормированияЦен AS ДокСтроки
INNER JOIN Документ_ПравилоФормированияЦен ДокШапка  ON ДокСтроки.IDDOC = ДокШапка.IDDOC
WHERE
ДокСтроки.СвояЦена = '     4   '
AND ДокСтроки.Вкл <> 0) AS Правила
ON Правила.Бренд = Номенклатура.Бренд
ПрямойЗапрос::Выполнить(Строка ТипОбъекта=ИндексированнаяТаблица, Строка ТекстВыполнения=, Число БезПодготовки=0) : no such column: Товар.Номенклатура
 


в чем-то я не прав, а в чем - не пойму...
p.s. про $nolock  помню, но у меня пока база дбф (sqlite), там это неважно, так?
  
Наверх
 
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #334 - 19. Ноября 2009 :: 05:17
Печать  
anko Ну по-порядку пожалуй...

Для начала с твоим запросом разберемся...
1. Всю типизацию необходимо выносить в самый верхний уровень запроса. Это обязательно. В подзапросах типизации значений быть не должно.
2. Теперь смотрим второй "подзапрос". Ты пишешь "ВНУТРЕННЕЕ" соединение, а соответственно ты хочешь чтобы из первой таблицы отсеклись все строки которые не встречаются во второй. А теперь ответь на вопрос... а может быть в таблице СТРОК документа "А" быть строки допустим документа "Б"??? В данном случае простое левое соединение даст тот же самый результат.
3. Теперь рассмотрим запрос в целом... Первый подзапрос называется ТОВАР (таблица с полями Номенклатура, Свойства, Бренд). Второй подзапрос называется ПРАВИЛА (колонки Бренд, Цена, Наценка, Приоритет).
Теперь определим что из этих двух таблиц мы хотим получить: Номенклатура, Цена, Приоритет...
Сразу видно что в таблице ТОВАР нам надо 2 колонки Номенклатура + Бренд (для связи), в таблице ПРАВИЛА нам надо колонки Бренд (для связи) + Цена + Приоритет. Теперь, у нас в результирующую колонку должна попасть только та номенклатура которая содержится в таблице ПРАВИЛА. Соответственно либо мы ТОВАР соединяем с ПРАВИЛА через внутреннее, либо ПРАВИЛА с ТОВАР через левое. По первому варианту, (как я понимаю) мы получим двойной прогон таблицы ПРАВИЛА. Сначала для соединения, потом для отсечения из результата того что нет в ПРАВИЛА. Во втором варианте мы получим то что нам надо, при этом ничего лишнего не будет.
Учитывая все вышеизложенное я думаю что запрос должен выглядеть так:
Код
Выбрать все
ВЫБРАТЬ
	Товар.Номенклатура КАК [Номенклатура $Справочник.Номенклатура]
	,Правила.Цена КАК [Цена $Справочник.ТипыЦен]
	,Правила.Приоритет КАК [Приоритет $Число]
ИЗ
	(ВЫБРАТЬ
		$ДокШапка.Бренд КАК Бренд
		,$ДокСтроки.ЦенаПоставщика КАК Цена
		,$ДокСтроки.Приоритет КАК Приоритет
	ИЗ ДокументСтроки.ПравилоФормированияЦен КАК ДокСтроки $nolock
	ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПравилоФормированияЦен КАК ДокШапка $nolock
	ПО $ДокСтроки.ТекущийДокумент = $ДокШапка.ТекущийДокумент
	ГДЕ $ДокСтроки.СвояЦена = :ТипЦен
	И $ДокСтроки.Вкл <> 0) КАК Правила
ЛЕВОЕ СОЕДИНЕНИЕ
	(ВЫБРАТЬ
		$Номенклатура.ТекущийЭлемент КАК Номенклатура
		,$Свойства.Бренд КАК Бренд
	ИЗ Справочник.Номенклатура КАК Номенклатура $nolock
	ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СвойстваНоменклатуры КАК Свойства
	ПО $Номенклатура.ОсновноеСвойство = $Свойства.ТекущийЭлемент
	) КАК Товар
ПО Правила.Бренд = Товар.Бренд 



Пы.сы. покажи данный запрос с режим отладки.

Ну и наконец что касается "Почему с внутреннее работает дольше". Смотри в сообщения парсера в которых указаны индексы которые подобраны для выполнения и их стоимость. Чем ниже стоимость тем лучше составлен твой запрос. И даже если ты попадаешь в индекс надо знать отличие в работе соединений. Почитай книжки по SQL.
« Последняя редакция: 19. Ноября 2009 :: 07:56 - vandalsvq »  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
classic
Senior Member
****
Отсутствует


I Love YaBB 2!

Сообщений: 330
Местоположение: г. Харьков
Зарегистрирован: 22. Мая 2006
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #335 - 19. Ноября 2009 :: 06:44
Печать  
Спасибо за подробное разжевывание различий левого и внутреннего соединения. Я как-то даже не задумывался о том, что левое побыстрее будет.
  
Наверх
 
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #336 - 19. Ноября 2009 :: 07:02
Печать  
Кстати вот еще почитайте по соединениям
http://www.1cpp.ru/forum/YaBB.pl?num=1217939813/21#21
Тов. Dmitro очень подробно разжевал этот вопрос.
И вот еще неплохо было бы почитать
http://www.intuit.ru/department/database/sql/5/ (Соединения и теоретико-множественные операции над отношениями).
Там на интуите кстати для начинающих неплохо разжеван язык SQL. Подмигивание

Но вообще все случаи так или иначе индивидуальны. И я могу вполне ошибаться на счет работы внутреннего и левого соединения.
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
Захар Малиновский
Junior Member
**
Отсутствует


1C++ active user

Сообщений: 53
Местоположение: г. Харьков
Зарегистрирован: 26. Февраля 2009
Re: Класс "ПрямойЗапрос"
Ответ #337 - 19. Ноября 2009 :: 08:41
Печать  
Странно  , а почему нет возможности при использовании , скажем , ВТ $РегистрОстатки указать ей ставить нужный мне хинт, например HOLDLOCK ?
В КОП-е вроде железно прописано NOLOCK.
Что коп писался для конфы, в которой табличные блокировки не заменены на собственные.
Ведь любой документ при проведении делает "delete from $РегистрОстатки .....".  И в это время чтение с NOLOCK мне ну ни как не пойдёт.
А доработку к классу сделать можно, так чтобы эта доработка потом учитывалась автором, при последующих уже его ,автора доработках класса?
  
Наверх
IP записан
 
Захар Малиновский
Junior Member
**
Отсутствует


1C++ active user

Сообщений: 53
Местоположение: г. Харьков
Зарегистрирован: 26. Февраля 2009
Re: Класс "ПрямойЗапрос"
Ответ #338 - 19. Ноября 2009 :: 09:02
Печать  
может пятый параметр в ВТ $РегистрОстатки сделаешь ? (для хинтов в скобках)
  
Наверх
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #339 - 19. Ноября 2009 :: 09:11
Печать  
Параметры в ВТ добавлять совсем не хочется. Может просто для собственных задач ты сам изменишь то что тебе надо? Достаточно вынести публичный атрибут в котором указывать хинты. Соответственно конечно прийдется немного покарпеть над перепиской. Но это ведь совсем немного.
А мне такой функционал пока не очень нужен. Точнее совсем не нужен Улыбка
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
berezdetsky
1c++ power user
Отсутствует


barba non facit sisadminum

Сообщений: 1986
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #340 - 19. Ноября 2009 :: 09:13
Печать  
Захар Малиновский писал(а) 19. Ноября 2009 :: 08:41:
Странно  , а почему нет возможности при использовании , скажем , ВТ $РегистрОстатки указать ей ставить нужный мне хинт, например HOLDLOCK ?
В КОП-е вроде железно прописано NOLOCK.
Что коп писался для конфы, в которой табличные блокировки не заменены на собственные.

Точно так же работают ВТ 1С++ и штатные механизмы запросов 1С. Если для твоей реализации блокировок это неприемлемо, IMHO, нужно менять твою реализацию.
  

пароль как коньяк, чем больше звездочек, тем лучше
Наверх
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #341 - 19. Ноября 2009 :: 09:17
Печать  
classic писал(а) 19. Ноября 2009 :: 06:44:
Спасибо за подробное разжевывание различий левого и внутреннего соединения. Я как-то даже не задумывался о том, что левое побыстрее будет.

Однозначного ответа на то что быстрее нет. По крайней мере все очень сильно зависит от ситуации... т.е. от БД Улыбка
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
anko
YaBB Newbies
*
Отсутствует


1C++ rocks!

Сообщений: 9
Зарегистрирован: 11. Ноября 2009
Re: Класс "ПрямойЗапрос"
Ответ #342 - 19. Ноября 2009 :: 09:32
Печать  
vandalsvq
Большое спасибо.
Цитата:
Пы.сы. покажи данный запрос с режим отладки.

Код
Выбрать все
SELECT
	Товар.Номенклатура AS [Номенклатура $Справочник.Номенклатура]
	,Правила.Цена AS [Цена $Справочник.ТипыЦен]
	,Правила.Приоритет AS [Приоритет $Число]
FROM
	(SELECT
		ДокШапка.Бренд AS Бренд
		,ДокСтроки.ЦенаПоставщика AS Цена
		,ДокСтроки.Приоритет AS Приоритет
	FROM ДокументСтроки_ПравилоФормированияЦен AS ДокСтроки
	LEFT JOIN Документ_ПравилоФормированияЦен AS ДокШапка
	ON ДокСтроки.IDDOC = ДокШапка.IDDOC
	WHERE ДокСтроки.СвояЦена = '     4   '
	AND ДокСтроки.Вкл <> 0) AS Правила
LEFT JOIN
	(SELECT
		Номенклатура.ID AS Номенклатура
		,Свойства.ЗначениеСвойства AS Бренд
	FROM Справочник_Номенклатура AS Номенклатура
	LEFT JOIN Справочник_СвойстваНоменклатуры AS Свойства
	ON Номенклатура.ОсновноеСвойство = Свойства.ID
	) AS Товар
ON Правила.Бренд = Товар.Бренд
Подбор индекса для таблицы SC84:
	Ограничения:
	В кэше не найдено
	Индекс не выбран.
	Стоимость: 9984
Подбор индекса для таблицы SC562:
	Ограничения: ID=;
	В кэше не найдено
	Выбран индекс IDD: ID
	Стоимость: 18
Подбор индекса для таблицы DT39812:
	Ограничения: SP39806[СвояЦена]=;
	Найдено в кэше
	Индекс не выбран.
	Стоимость: 9988
Подбор индекса для таблицы DH39812:
	Ограничения: IDDOC=;
	Найдено в кэше
	Выбран индекс ID: IDDOC
	Стоимость: 8
Время подготовки запроса: 26 мс, время выполнения запроса: 23505 мс.
 


долго....
  
Наверх
 
IP записан
 
vandalsvq
1c++ power user
Отсутствует


Я всего лишь als-особиратель
;-)

Сообщений: 2487
Местоположение: Уфа
Зарегистрирован: 18. Июля 2007
Пол: Мужской
Re: Класс "ПрямойЗапрос"
Ответ #343 - 19. Ноября 2009 :: 09:53
Печать  
Согласен. Есть предложение по оптимизации. Но мне бы или твой MD, а еще лучше базу данных Подмигивание

Пы.сы. опять таки исходя из твоей задачи... тебе надо вытащить элемент справочника номенклатура, есть поле ОсновноеСвойство. Можно конечно сделать левое соединение со справочником (не использую вложенный запрос, и без использования справочника Свойства) просто сделав левое соединение по данному полю со справочником Номенклатура. Индекса там нет, но если очень нужнол (большие объемы, частые запросы и т.п.) можно поставить отбор и сортировку. Больше в голову ничего особо не приходит.
  

Отхожу от дел. Долго и мучительно.
Наверх
IP записан
 
Захар Малиновский
Junior Member
**
Отсутствует


1C++ active user

Сообщений: 53
Местоположение: г. Харьков
Зарегистрирован: 26. Февраля 2009
Re: Класс "ПрямойЗапрос"
Ответ #344 - 19. Ноября 2009 :: 10:01
Печать  
berezdetsky писал(а) 19. Ноября 2009 :: 09:13:
Захар Малиновский писал(а) 19. Ноября 2009 :: 08:41:
Странно  , а почему нет возможности при использовании , скажем , ВТ $РегистрОстатки указать ей ставить нужный мне хинт, например HOLDLOCK ?
В КОП-е вроде железно прописано NOLOCK.
Что коп писался для конфы, в которой табличные блокировки не заменены на собственные.

Точно так же работают ВТ 1С++ и штатные механизмы запросов 1С. Если для твоей реализации блокировок это неприемлемо, IMHO, нужно менять твою реализацию.


Тут я с вами не соглашусь.
Прямой запрос у меня используеться в отчёте. А отчет в режиме "хотим по всем клиентам удовлетворяющим такому то условию" означает что ДО выполнения select-a я не знаю какие клиенты попадут в отчет. Поэтому применить свой механизм блокировок чтобы заблокировать взаиморасчёты именно этих клиентов, тех которые БУДУТ участвовать в select-e нецелесообрано.  Это долго. Только полностью на таблицу взаиморасчётов быстро.  А что вы ещё предложите ?   Кстате свои блокировки это  sp_getapplock(объект)  на каждого клиента , если по клиенту что то меняеться.
Так вот вот было бы классно и просто переложить локи запросов отчётов на sql сервер,  если бы запрос именно отчёта (т.е. КОП ПрямойЗапрос) налОживал Shared Locks на то что он читает до конца транзакции т.е. метод "выполнить" в транзакции выполнять. Это гарантирует что никто не поменяет взаиморасчёты, пока отчёт выполняет метод "выполнить" по клиентам , которые попали в отчёт.   
И собственные блокировки тут не суть дела.  У вас (без изменённых блокировок) ведь тоже кто то что то может провести , удалить из таблицы взаиморасчётов, чтобы потом записать новые движения , пока ваш отчёт читает данные.
  
Наверх
IP записан
 
Переключение на Главную Страницу Страницы: 1 ... 21 22 [23] 24 25 ... 60
ОтправитьПечать