Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
 Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Здравствуйте уважаемые форумчане.
Подскажите пожалуйста, можно ли как-то ускорить следующий запрос:

Declare @iElementID_Root int,
@iElementID int,
@iContractorID int
Set @iElementID_Root  = 6001;
Set @iElementID  = 1;
Set @iContractorID =4;

	 WITH NodeLevel AS (SELECT     iNodeElementID, ND.iElementID AS iElementID_Root, iElementID_Parent, ND.iElementID, 
                              decNodeElementCnt, CAST(ISNULL(decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode,
                               
                              iIndex as iIndex_Parent, iIndex
                                              FROM         dbo.tblNodeElement ND join dbo.tblElement EL On ND.iElementID =EL.iElementID
                                              WHERE     (iElementID_Parent IS NULL)
                                              UNION ALL
                                              SELECT     nd.iNodeElementID, NodeLevel_2.iElementID_Root, nd.iElementID_Parent, nd.iElementID, nd.decNodeElementCnt, 
                                                                    CAST(ISNULL(NodeLevel_2.decNodeElementCnt, 0) 
                                                                    * ISNULL(nd.decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode, NodeLevel_2.iIndex, EL.iIndex
                                              FROM         dbo.tblNodeElement ND Join dbo.tblElement EL On ND.iElementID = EL.iElementID INNER JOIN
                                                                    NodeLevel AS NodeLevel_2 ON nd.iElementID_Parent = NodeLevel_2.iElementID
                                                                    Where NodeLevel_2.iElementID_Root = @iElementID_Root
                                                                          ),
                                                                          
     CTE As (Select NL.iNodeElementID, iElementID_Root, iElementID_Parent, iElementID, decNodeElementCnt, decNodeElementCntSumOnNode, iIndex_Parent, iIndex,
                   CAST(CASE WHEN IsNull(NL.decNodeElementCntSumOnNode , 0) =0 then 1 Else NL.decNodeElementCntSumOnNode End
                   / (CASE WHEN ISNULL(NL.decNodeElementCnt, 0) = 0 THEN 1 ELSE NL.decNodeElementCnt END) AS decimal(8, 3)) AS decNodeCnt, decZehNorm, ZN.iContractorID                    
             From NodeLevel NL Join tblZehNorm ZN On NL.iNodeElementID = ZN.iNodeElementID
             Where ZN.iContractorID = @iContractorID And NL.iElementID = @iElementID 
                               )
                                                                         
select Distinct Cast(a.Normsum as decimal (8,3))  
FROM         CTE Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From CTE T2 
                                Where ((CTE.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( CTE.iElementID_Parent = T2.iElementID_Parent))
                                  and CTE.iElementID_Root = T2.iElementID_Root
                                  and cTE.iElementID = T2.iElementID
                                  )a     


Имеется рекурсивный запрос (первая часть), общее табличное выражение - как подготовка данных к последующему запросу (вторая часть) и наконец (третья часть) вывод суммы по конкретным исходным данным заданым в начале.
К сожалению рекурсивный запрос прорабатывает массу данных которые прорабатывать бы не нужно, в частности выводит все возможные iElementID, хотя iElementID задан конкретно. Но и внести конкретное условие в рекурсию не получается, так как в данном конкретном случае элемент с iElementID = 1 может входить как в главную ветку iElementID_Root, так и в какую-то подветку (с совершенно другим iElementID) которая в свою очередь входит в iElementID_Root. Т.е. Я не могу задать условие Where NodeLevel.iElementID = @iElementID в рекурсивном запросе - обрежет нужные данные. А не задавая этого условия - наоборот обрабатывается слишком много лишних данных.

И по третьей части тоже вопрос. Хорошо если мне необходима общая сумма по данным конкретным условиям, но помимо этого нужна здесь же сумма по другим условиям (группировка по iElementID_Root, iElementID с теми же самыми условиями что и выше, но без iContractorID. Что ж теперь еще один outer applay рядом городить? Это опять же потеря скорости.
28 ноя 13, 17:28    [15207504]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Изерлонер

но помимо этого нужна здесь же сумма по другим условиям (группировка по iElementID_Root, iElementID с теми же самыми условиями что и выше, но без iContractorID. Что ж теперь еще один outer applay рядом городить? Это опять же потеря скорости.


Имею ввиду следующий запрос с двумя outer applay (хороший оператор, весьма понравился, но видимо не везде его можно использовать):

Declare @iElementID_Root int,
@iElementID int,
@iContractorID int
Set @iElementID_Root  = 6001;
Set @iElementID  = 1;
Set @iContractorID =4;

	 WITH NodeLevel AS (SELECT     iNodeElementID, ND.iElementID AS iElementID_Root, iElementID_Parent, ND.iElementID, 
                              decNodeElementCnt, CAST(ISNULL(decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode,
                               
                              iIndex as iIndex_Parent, iIndex
                                              FROM         dbo.tblNodeElement ND join dbo.tblElement EL On ND.iElementID =EL.iElementID
                                              WHERE     (iElementID_Parent IS NULL)
                                              UNION ALL
                                              SELECT     nd.iNodeElementID, NodeLevel_2.iElementID_Root, nd.iElementID_Parent, nd.iElementID, nd.decNodeElementCnt, 
                                                                    CAST(ISNULL(NodeLevel_2.decNodeElementCnt, 0) 
                                                                    * ISNULL(nd.decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode, NodeLevel_2.iIndex, EL.iIndex
                                              FROM         dbo.tblNodeElement ND Join dbo.tblElement EL On ND.iElementID = EL.iElementID INNER JOIN
                                                                    NodeLevel AS NodeLevel_2 ON nd.iElementID_Parent = NodeLevel_2.iElementID
                                                                    Where NodeLevel_2.iElementID_Root = @iElementID_Root
                                                                          ),
                                                                          
     CTE As (Select NL.iNodeElementID, iElementID_Root, iElementID_Parent, iElementID, decNodeElementCnt, decNodeElementCntSumOnNode, iIndex_Parent, iIndex,
                   CAST(CASE WHEN IsNull(NL.decNodeElementCntSumOnNode , 0) =0 then 1 Else NL.decNodeElementCntSumOnNode End
                   / (CASE WHEN ISNULL(NL.decNodeElementCnt, 0) = 0 THEN 1 ELSE NL.decNodeElementCnt END) AS decimal(8, 3)) AS decNodeCnt, decZehNorm, ZN.iContractorID                    
             From NodeLevel NL Join tblZehNorm ZN On NL.iNodeElementID = ZN.iNodeElementID
             --Where ZN.iContractorID = @iContractorID And NL.iElementID = @iElementID 
                               )
                                                                         
select Distinct Cast(a.Normsum as decimal (8,3)) ZehNormSum, Cast(b.Normsum as decimal (8,3)) IzdNormSum 
FROM         CTE Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From CTE T2 
                                Where ((CTE.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( CTE.iElementID_Parent = T2.iElementID_Parent))
                                  and CTE.iElementID_Root = T2.iElementID_Root
                                  and cTE.iElementID = T2.iElementID
                                  and T2.iContractorID = @iContractorID
                                  and T2.iElementID = @iElementID)a  
                                  
                  Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From CTE T2 
                                Where ((CTE.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( CTE.iElementID_Parent = T2.iElementID_Parent))
                                  and CTE.iElementID_Root = T2.iElementID_Root
                                  and cTE.iElementID = T2.iElementID
                                  and T2.iElementID = @iElementID)b
28 ноя 13, 17:36    [15207548]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
[quot Изерлонер]
Изерлонер
с двумя outer applay
Cross apply конечно же.
28 ноя 13, 17:38    [15207554]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
o-o
Guest
вот отработала рекурсия, и слейте все полученное (ну или отрезав лишнее) во временную таблицу.
и с ней уже дальше работайте.
всюду, где встречается CTE, все будет высчитываться заново.
зачем 100 раз считать, если можно 1 раз сохранить
28 ноя 13, 17:44    [15207588]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
o-o
всюду, где встречается CTE, все будет высчитываться заново.
зачем 100 раз считать, если можно 1 раз сохранить

Я правильно понял, везде где встречается CTE в последующих запросах заново запускается расчет с самого начала, и рекурсивный запрос запускается при каждом CTE?

Не просто так спрашиваю - это для меня неожиданность. Дело в том что я планировал сбрасывать все во временную таблицу, продумывал вопрос, но прочитал в "Murach_SQL_Server_2008_for_Developers" что общее табличное выражение (или derieved tabel) работает быстрее временных таблиц. ... Может быть что-то не верно понял, с английским не очень дружу (немецкий изучал).
28 ноя 13, 17:52    [15207620]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
o-o
Guest
Изерлонер,
CTE это такое ad hoc view.
оно в тексте запроса просто раскрывается, подставляется его определение.
т.е. если Вы его в запросе N раз использовали, N раз оно и посчитается.
удобно использовать, если надо получить одну таблицу, из нее другую, из той третью и т.д.
вместо SELECT * FROM (SELECT * FROM (SELECT * FROM (...())))
вынести каждый последующий запрос в свое CTE_n, использующее только предыдущее CTE_n-1.
читать удобнее.
а при выполнении вся матрешка будет обратно собрана.

ну и рекурсивное CTE -- отдельная песня.
если именно рекурсия нужна, то как еще.
другое дело, зачем саму эту рекурсию 100 раз считать
28 ноя 13, 18:18    [15207767]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Переделал с табличной переменной:
Declare @iElementID_Root int,
@iElementID int,
@iContractorID int
Declare @tab_level TABLE 
(iNodeElementID int, iElementID_Root int, iElementID_Parent int, iElementID int, decNodeElementCnt decimal(8,3), 
decNodeElementCntSumOnNode decimal(8,3), iIndex_Parent int, iIndex int, decNodeCnt decimal(8,3), 
decZehNorm decimal(8,3), iContractor int)

Set @iElementID_Root  = 6001;
Set @iElementID  = 1;
Set @iContractorID =4;

	 WITH NodeLevel AS (SELECT     iNodeElementID, ND.iElementID AS iElementID_Root, iElementID_Parent, ND.iElementID, 
                              decNodeElementCnt, CAST(ISNULL(decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode,
                               
                              iIndex as iIndex_Parent, iIndex
                                              FROM         dbo.tblNodeElement ND join dbo.tblElement EL On ND.iElementID =EL.iElementID
                                              WHERE     (iElementID_Parent IS NULL)
                                              UNION ALL
                                              SELECT     nd.iNodeElementID, NodeLevel_2.iElementID_Root, nd.iElementID_Parent, nd.iElementID, nd.decNodeElementCnt, 
                                                                    CAST(ISNULL(NodeLevel_2.decNodeElementCnt, 0) 
                                                                    * ISNULL(nd.decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode, NodeLevel_2.iIndex, EL.iIndex
                                              FROM         dbo.tblNodeElement ND Join dbo.tblElement EL On ND.iElementID = EL.iElementID INNER JOIN
                                                                    NodeLevel AS NodeLevel_2 ON nd.iElementID_Parent = NodeLevel_2.iElementID
                                                                    Where NodeLevel_2.iElementID_Root = @iElementID_Root
                                                                          )

Insert @tab_level 
Select NL.iNodeElementID, iElementID_Root, iElementID_Parent, iElementID, decNodeElementCnt, decNodeElementCntSumOnNode, iIndex_Parent, iIndex,
                   CAST(CASE WHEN IsNull(NL.decNodeElementCntSumOnNode , 0) =0 then 1 Else NL.decNodeElementCntSumOnNode End
                   / (CASE WHEN ISNULL(NL.decNodeElementCnt, 0) = 0 THEN 1 ELSE NL.decNodeElementCnt END) AS decimal(8, 3)) AS decNodeCnt, decZehNorm, ZN.iContractorID                    
                   From NodeLevel NL Join tblZehNorm ZN On NL.iNodeElementID = ZN.iNodeElementID
              
  --Select * from @tab_level                             
                                                                         
select Distinct Cast(a.Normsum as decimal (8,3)) ZehNormSum, Cast(b.Normsum as decimal (8,3)) IzdNormSum 
FROM         @tab_level T1 Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From @tab_level T2 
                                Where ((T1.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( T1.iElementID_Parent = T2.iElementID_Parent))
                                  and T1.iElementID_Root = T2.iElementID_Root
                                  and T1.iElementID = T2.iElementID
                                  and T2.iContractor = @iContractorID
                                  and T2.iElementID = @iElementID)a  
                                  
                  Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From @tab_level T2 
                                Where ((T1.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( T1.iElementID_Parent = T2.iElementID_Parent))
                                  and T1.iElementID_Root = T2.iElementID_Root
                                  and T1.iElementID = T2.iElementID
                                  and T2.iElementID = @iElementID)b   

Такой запрос отрабатывает в пять раз медленнее предыдущего :( 10 сек против 2.
28 ноя 13, 18:22    [15207786]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
o-o
Guest
Изерлонер,

а кто просил в табличную переменную сохранять?
сколько строк Вы в нее положили?
переменные типа table на небольших объемах полезны,
для них статистика не собирается, грубо говоря, если не использовать хинт,
оптимизатор считает, что в @tab_level лежит одна строка.

попробуйте все в #tmp сохранить
28 ноя 13, 18:30    [15207819]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
pkarklin
Member

Откуда: Москва (Муром)
Сообщений: 74925
Изерлонер,

Запрос нельзя оптимизировать, глядя только на его текст. А наличие DISTINCT может говорить о том, или что-то лишнее выбирается в CTE или в запросах с CROSS APPLY не хватает каких-либо условий.
28 ноя 13, 18:30    [15207820]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
А вот так уже на много лучше, почти моментально выдал :

Declare @iElementID_Root int,
@iElementID int,
@iContractorID int
Declare @tab_level TABLE 
(iNodeElementID int, iElementID_Root int, iElementID_Parent int, iElementID int, decNodeElementCnt decimal(8,3), 
decNodeElementCntSumOnNode decimal(8,3), iIndex_Parent int, iIndex int, decNodeCnt decimal(8,3), 
decZehNorm decimal(8,3), iContractor int)

Set @iElementID_Root  = 6000;
Set @iElementID  = 1;
Set @iContractorID =4;

	 WITH NodeLevel AS (SELECT     iNodeElementID, ND.iElementID AS iElementID_Root, iElementID_Parent, ND.iElementID, 
                              decNodeElementCnt, CAST(ISNULL(decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode,
                               
                              iIndex as iIndex_Parent, iIndex
                                              FROM         dbo.tblNodeElement ND join dbo.tblElement EL On ND.iElementID =EL.iElementID
                                              WHERE     (iElementID_Parent IS NULL)
                                              UNION ALL
                                              SELECT     nd.iNodeElementID, NodeLevel_2.iElementID_Root, nd.iElementID_Parent, nd.iElementID, nd.decNodeElementCnt, 
                                                                    CAST(ISNULL(NodeLevel_2.decNodeElementCnt, 0) 
                                                                    * ISNULL(nd.decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode, NodeLevel_2.iIndex, EL.iIndex
                                              FROM         dbo.tblNodeElement ND Join dbo.tblElement EL On ND.iElementID = EL.iElementID INNER JOIN
                                                                    NodeLevel AS NodeLevel_2 ON nd.iElementID_Parent = NodeLevel_2.iElementID
                                                                    Where NodeLevel_2.iElementID_Root = @iElementID_Root
                                                                          )

Insert @tab_level 
Select NL.iNodeElementID, iElementID_Root, iElementID_Parent, iElementID, decNodeElementCnt, decNodeElementCntSumOnNode, iIndex_Parent, iIndex,
                   CAST(CASE WHEN IsNull(NL.decNodeElementCntSumOnNode , 0) =0 then 1 Else NL.decNodeElementCntSumOnNode End
                   / (CASE WHEN ISNULL(NL.decNodeElementCnt, 0) = 0 THEN 1 ELSE NL.decNodeElementCnt END) AS decimal(8, 3)) AS decNodeCnt, decZehNorm, ZN.iContractorID                    
                   From NodeLevel NL Join tblZehNorm ZN On NL.iNodeElementID = ZN.iNodeElementID
                   Where iElementID = @iElementID 
                                        
                                                                         
select Distinct Cast(a.Normsum as decimal (8,3)) ZehNormSum, Cast(b.Normsum as decimal (8,3)) IzdNormSum 
FROM         @tab_level T1 Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From @tab_level T2 
                                Where ((T1.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( T1.iElementID_Parent = T2.iElementID_Parent))
                                  and T1.iElementID_Root = T2.iElementID_Root
                                  and T1.iElementID = T2.iElementID
                                  and T2.iContractor = @iContractorID
                                  )a  
                                  
                  Cross Apply (Select SUM(T2.decZehNorm * T2.decNodeCnt )  AS Normsum 
                                From @tab_level T2 
                                Where ((T1.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( T1.iElementID_Parent = T2.iElementID_Parent))
                                  and T1.iElementID_Root = T2.iElementID_Root
                                  and T1.iElementID = T2.iElementID
                                  )b   
28 ноя 13, 18:32    [15207829]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
pkarklin
Изерлонер,

Запрос нельзя оптимизировать, глядя только на его текст. А наличие DISTINCT может говорить о том, или что-то лишнее выбирается в CTE или в запросах с CROSS APPLY не хватает каких-либо условий.

Да в общем-то понятно. Я как бы и не ожидаю конкретных решений. Ну не выкладывать же сюда техзадание на разработку всей базы, кому оно надо? Просто для опытного человека ошибки в логике наверное сразу заметны, и по крайней мере он может подсказать какие-то общие моменты, образцы, которых я просто не знаю по отсутствию такого опыта. ... Вот с Cross Apply так получилось например, я этой конструкции просто не знал о_о подсказал, а без него "городушки" еще хлеще были.
Насчет Distinct - да надо разобраться, выдаваемый результат получается в нескольких строчках с одними и теми же данными, доберусь еще.
28 ноя 13, 18:41    [15207872]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Изерлонер
Я правильно понял, везде где встречается CTE в последующих запросах заново запускается расчет с самого начала, и рекурсивный запрос запускается при каждом CTE?
Не всегда, может повезёт и поставится Спул. И к сожалению нет пока хинта на принудительный спул некоего подзапроса.

А вообще ваш запрос жесть. Оформлять надо правильно вы исправлять мелкие баги описания. (алиасы, схемы, скобки только для OR ...)
Дерево жесть: все базовые ноды + подветка (@iElementID_Root)? Не эффективно так отбирать данные.
И не надо пихать в CTE общую часть (dbo.tblElement).
А далее отфильтровка одного значения? (@iElementID)

Зачем ставить в APPLY равенство iElementID, если оно итак одинаковое во все таблице (= @iElementID)?
Оба APPLY равны, но отличаются только по iContractor.
Можно и за один запрос это сделать.
DISTINCT агрегаток - жесть! Может вам нужно группировка по [iElementID] ?

Да и вообще это можно за один запрос сделать, без всяких APPLY. Обыкновенное агрегирование. Главное правильно его задать.

Изерлонер, ужас. Учитесь излагать мысли, а не лишь бы написать кое как. Никто банально не поймёт смысл этого запроса.
DECLARE	@iElementID_Root	Int = 6000
,	@iElementID		Int = 1
,	@iContractorID		Int = 4
DECLARE	@tab_level TABLE (
	iNodeElementID			Int
,	iElementID_Root			Int
,	iElementID_Parent		Int
,	iElementID			Int
,	decNodeElementCnt		Decimal(8,3)
,	decNodeElementCntSumOnNode	Decimal(8,3)
,	iIndex_Parent			Int
,	iIndex				Int
,	decNodeCnt			Decimal(8,3)
,	decZehNorm			Decimal(8,3)
,	iContractor			Int
)

;WITH [NodeLevel] AS (
	SELECT	ND.iElementID			AS iElementID_Root
	,	EL.iIndex			AS iIndex_Parent
	,	ND.iNodeElementID
	,	ND.iElementID_Parent
	,	ND.iElementID
	,	ND.decNodeElementCnt
	,	IsNull(ND.decNodeElementCnt,0)	AS decNodeElementCntSumOnNode
	FROM	dbo.tblNodeElement	ND
	JOIN	dbo.tblElement		EL ON ND.iElementID = EL.iElementID
	WHERE	iElementID_Parent IS NULL
UNION ALL
	SELECT	NL.iElementID_Root
	,	NL.iIndex
	,	ND.iNodeElementID
	,	ND.iElementID_Parent
	,	ND.iElementID
	,	ND.decNodeElementCnt
	,	Cast(IsNull(ND.decNodeElementCnt,0)
		   * IsNull(NL.decNodeElementCnt,0) AS Decimal(8,3))
	FROM	[NodeLevel]		NL
	JOIN	dbo.tblNodeElement	ND ON ND.iElementID_Parent = NL.iElementID
	WHERE	NL.iElementID_Root = @iElementID_Root
)	INSERT	@tab_level
	SELECT	NL.iNodeElementID
	,	NL.iElementID_Root
	,	NL.iElementID_Parent
	,	NL.iElementID
	,	NL.decNodeElementCnt
	,	NL.decNodeElementCntSumOnNode
	,	NL.iIndex_Parent
	,	EL.iIndex
	,	Cast(IsNull(NullIf(NL.decNodeElementCntSumOnNode,0),1)
		   / IsNull(NullIf(NL.decNodeElementCnt         ,0),1) AS Decimal(8,3))	AS decNodeCnt
	,	ZN.decZehNorm
	,	ZN.iContractorID
	FROM	[NodeLevel]	NL
	JOIN	dbo.tblElement	EL ON EL.iElementID	= NL.iElementID
	JOIN	dbo.tblZehNorm	ZN ON NL.iNodeElementID	= ZN.iNodeElementID
	WHERE	NL.iElementID = @iElementID

SELECT	DISTINCT
	Cast(S.NormsumContractor AS Decimal(8,3))	ZehNormSum
,	Cast(S.Normsum		 AS Decimal(8,3))	IzdNormSum
--,	S.iElementID	-- !
FROM	@tab_level	I CROSS APPLY (
	SELECT	Sum(S.decZehNorm * S.decNodeCnt)AS Normsum
	,	Sum(CASE WHEN S.iContractor = @iContractorID
		THEN S.decZehNorm * S.decNodeCnt
		ELSE 0 END)			AS NormsumContractor
	FROM	@tab_level S
	WHERE	S.iElementID		 = I.iElementID		-- ? @iElementID
	AND (	S.iElementID_Parent	 = I.iElementID_Parent	-- Sibling?
	 OR	S.iIndex_Parent		!= I.iIndex_Parent
	AND	S.iElementID_Parent	 = S.iIndex_Parent / 100-- ? o_O
	AND	S.iElementID_Root	 = I.iElementID_Root)	-- ? @iElementID_Root
		)	S
Ищё исправлять и исправлять...
Исправьте как надо, добавьте колонки и объясните что вам надо.
Связку APPLY я так и не понял. Распишите. И CTE тоже. И смысл всех переменных.

Ваш CTE неверен тем что надо смотреть не сверху вниз по дереву, а снизу вверх.
Проблема в том что вы вычисляете не изменяемые данные каждый раз в запросе (decNodeElementCntSumOnNode), рекурсивные.
А они должны пере вычисляться во время изменения данных. Тогда вам придётся просто их тупо взять готовыми из таблицы, без всяких рекурсий.
А для дерева вам возможно подойдёт HierarchyID. Можете сразу получать Root или всех парентов сразу.
28 ноя 13, 23:06    [15208823]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
+

Mnior, знаю что запрос жесть, ну учиться мне еще и учиться. Я на sql_ex.ru на первом этапе (обучающий), там решаю задачи пока с той стратегией – лишь бы решить задачу. Не до оптимизации там пока. В результате часто цена моих запросов на два порядка больше чем запросов от профессионалов. Тот же подход в работе – главное и первоочередное решить задачу, любыми путями хоть землю грызи, хоть из Питера в Москву через Нью-Йорк езжай, а что бы выдавало нужные и «правильные» результаты. А уж как быстро это вопрос второй (который конечно же тоже важен, но прежде всего результат, потом скорость). Отсюда и такие дикие запросы и нагромождения.
«Учитесь излагать мысли, а не лишь бы написать кое как.»
Есть и такая проблема. На самом деле описать коротко, емко, в двух словах какую-то обширную область, и так что бы всем сразу и все было понятно это большое искусство.
У меня задача весьма тяжелая, предметная область включает множество ньюансов, часто даже без всякого программирования, просто «в реале» не понятно что и из чего следует настолько все запутанно и противоречиво. И становится понятно спустя довольно большой промежуток времени и порой довольно мучительно (особенно когда думаешь, а как вообще это реализовать, не имея пока еще ни навыков ни знаний? … Кстати добрые люди меня об этом предупреждали, еще когда все начиналось на этом форуме, когда вообще полный ноль был по базам данных(надеюсь я с того уровня хоть немного сдвинулся)), я не жалуюсь это скорее «муки творчества» и по большому счету мне вся эта тема очень нравится, сожалею только что раньше не занимался базами данных. Творчество это хорошо конечно, но от меня-то требуют результата и желательно «вчера». Результата в реале, в предметной области, а не какой-то там базы данных в которых никто из сотрудников и руководства вообще ничего не понимает (хорошо хоть не мешают и на том спасибо).
Если я пытаюсь подробно описать предметную область, базу данных, запросы и что мне надо задавая вопросы на форуме – всем резко становится скучно в теме никого не остается. И я никого не осуждаю – ну кому этот гемор нужен кроме меня? Тем, кто все же помог, даже просто советом, подсказкой я очень благодарен.
Практика показала что такой путь не эффективен. В лучшем случае мне даются советы по организации базы данных до которых я порой просто … не дорос. ( … хотя иногда …вот на соседней ветке по Access мне очень помог «Программист-Любитель», фактически без него ничего бы вообще не было бы.) Гораздо лучше спрашивать конкретно, а как сделать то-то или вот это, без пространного объяснения, а зачем вообще все это надо. Вроде и людей отвечающих мне не сильно напрягаю, не «заставляю» разбирать всю эту мутотень с предметной областью, и действительно получаю ответы, часто даже не те, что ожидал, но которые помогают решить какую-то задачу. Может я не прав, поправьте меня если что.



Теперь конкретно по запросу. Да, даже оформление у вас восхищает. И видно даже не вооруженным глазом что работает это на много быстрее. На выходе получаются однако, не те данные. Должно быть два значения, на деле таблица из значений по двум столбцам. До конца еще не разобрался (в процессе), отметил проблему с iIndex_Parent по вашему рекурсивному запросу туда попадает только индексы верхнего корневого уровня.
Вот что попадает в табличную переменную у меня:
iNodeElementID iElementID_Root iElementID_Parent iElementID decNodeElementCnt decNodeElementCntSumOnNode iIndex_Parent iIndex decNodeCnt decZehNorm iContractor
47117 6000 6000 1 NULL 0.000 600000 100 1.000 10.000 6
47117 6000 6000 1 NULL 0.000 600000 100 1.000 67.730 1
47117 6000 6000 1 NULL 0.000 600000 100 1.000 37.000 4
47117 6000 6000 1 NULL 0.000 600000 100 1.000 114.000 2
47117 6000 6000 1 NULL 0.000 600000 100 1.000 53.000 9
47117 6000 6000 1 NULL 0.000 600000 100 1.000 109.000 8
47117 6000 6000 1 NULL 0.000 600000 100 1.000 58.500 10
47117 6000 6000 1 NULL 0.000 600000 100 1.000 27.400 11
43626 6000 6023 1 NULL 0.000 602300 100 1.000 40.000 4
43059 6000 6020 1 NULL 0.000 602000 100 1.000 110.000 8
42850 6000 6016 1 NULL 0.000 601600 100 1.000 5.000 4
42718 6000 6015 1 NULL 0.000 601500 100 1.000 5.000 4
42482 6000 6011 1 NULL 0.000 601100 100 1.000 4.000 4
41853 6000 6005 1 NULL 0.000 600500 100 1.000 6.000 4


А вот то что у Вас:
iNodeElementID iElementID_Root iElementID_Parent iElementID decNodeElementCnt decNodeElementCntSumOnNode iIndex_Parent iIndex decNodeCnt decZehNorm iContractor
47117 6000 6000 1 NULL 0.000 600000 100 1.000 10.000 6
47117 6000 6000 1 NULL 0.000 600000 100 1.000 67.730 1
47117 6000 6000 1 NULL 0.000 600000 100 1.000 37.000 4
47117 6000 6000 1 NULL 0.000 600000 100 1.000 114.000 2
47117 6000 6000 1 NULL 0.000 600000 100 1.000 53.000 9
47117 6000 6000 1 NULL 0.000 600000 100 1.000 109.000 8
47117 6000 6000 1 NULL 0.000 600000 100 1.000 58.500 10
47117 6000 6000 1 NULL 0.000 600000 100 1.000 27.400 11
43626 6000 6023 1 NULL 0.000 600000 100 1.000 40.000 4
42850 6000 6016 1 NULL 0.000 600000 100 1.000 5.000 4
42718 6000 6015 1 NULL 0.000 600000 100 1.000 5.000 4
43059 6000 6020 1 NULL 0.000 600000 100 1.000 110.000 8
41853 6000 6005 1 NULL 0.000 600000 100 1.000 6.000 4
42482 6000 6011 1 NULL 0.000 600000 100 1.000 4.000 4


Ну и на выходе:
ZehNormSum IzdNormSum
97.000 646.630

и
ZehNormSum IzdNormSum
NULL 110.000
4.000 4.000
5.000 5.000
6.000 6.000
37.000 476.630
40.000 40.000

соответственно.
Я разбираюсь еще пока, прошу прощения, торможу.
29 ноя 13, 06:14    [15209428]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Mnior
Связку APPLY я так и не понял. Распишите. И CTE тоже. И смысл всех переменных.

Коротко. Предметная область - нормирование и контроль расхода материалов и запчастей на ремонт техники.
Запрос обсуждаемый в ветке должен выдавать суммарное количество материала (конкретной запчасти) iElementID из расчета на 1) цех (изделие может ремонтироваться в разных цехах и нормы расхода по цехам разные) и 2) на изделие (по сути сумма расходов всех цехов).
Вообще все это дело я загоняю в табличную функцию и затем проставляю эти данные (норма расхода на цех/норма расхода на изделие) в каждой строчке норматива для каждого материала (запчасти) по изделию. ... работает медленно.
Apply применяется для расчета сумм. Ранее применял Sum(...) over (Partition by ...), но туда условия суммирования загнать сложно оказалось, да и работало еще медленнее. Условия суммирования это как раз те ньюансы. Задаются посредством индексов взаимозаменяемости. Т.е. какой-то узел может быть взаимозаменяем с другим узлом более новым или старым, не суть - другим. И расчитать суммарное количество деталей из-за этих ньюансов становится проблематично. Для этого введены индексы взаимозаменяемости - одинаковые для взаимозаменяемых деталей и узлов.

СТЕ по большому счету нужен только что бы промежуточные данные получить из рекурсивного запроса.
Переменные
iElementID_Root -изделие
iElemetnID_Parent - "родительский" узел
iElementID - деталь (материал)
iContractorID - цех (он же в других таблицах поставщик, получатель и т.п. То есть данные цехов и всех контрагентов хранятся в одной таблице)
29 ноя 13, 06:31    [15209435]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Изерлонер
И расчитать суммарное количество деталей из-за этих ньюансов становится проблематично.

Вообще-то не возможно. Разное количество и номенклатура деталей может быть в узлах. Для того что бы задать какие-то критерии расчета придумал схему с базовой комплектацией узлов и деталей - в которой конкретное количество конкретных деталей. А то что не входит в базовую комплектацию расчитывается по своим правилам.
29 ноя 13, 06:35    [15209438]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Изерлонер
Запрос обсуждаемый в ветке должен выдавать... 1) ...2)...

Есть еще и 3) Это суммарное количество деталей конкретной номенклатуры (касается только деталей) установленных на изделии (не путать с нормой расхода!) реализуется несколько проще, у меня в отдельной скалярной фукции... но наверное имеет смысл сюда же эту часть отнести, порядок расчета точно такой же.

ALTER FUNCTION [dbo].[fnsElementCnt] (@iElementID_Root int, @iElementID int)
RETURNS decimal (8,3)
AS
BEGIN
	DECLARE @Result decimal (8, 3); 
	 WITH NodeLevel AS (SELECT     iNodeElementID, ND.iElementID AS iElementID_Root, iElementID_Parent, ND.iElementID, 
                              decNodeElementCnt, CAST(ISNULL(decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode,                              
                              iIndex as iIndex_Parent, iIndex
                                              FROM         dbo.tblNodeElement ND join dbo.tblElement EL On ND.iElementID =EL.iElementID
                                              WHERE     (iElementID_Parent IS NULL)
                                              UNION ALL
                                              SELECT     nd.iNodeElementID, NodeLevel_2.iElementID_Root, nd.iElementID_Parent, nd.iElementID, nd.decNodeElementCnt, 
                                                                    CAST(ISNULL(NodeLevel_2.decNodeElementCnt, 0) 
                                                                    * ISNULL(nd.decNodeElementCnt, 0) AS decimal(8, 3)) AS decNodeElementCntSumOnNode, NodeLevel_2.iIndex, EL.iIndex
                                              FROM         dbo.tblNodeElement ND Join dbo.tblElement EL On ND.iElementID = EL.iElementID INNER JOIN
                                                                    NodeLevel AS NodeLevel_2 ON nd.iElementID_Parent = NodeLevel_2.iElementID
                                                                    Where NodeLevel_2.iElementID_Root = @iElementID_Root
                                                                          And nd.iElementID =@iElementID)
                                                                          
select @Result = a.decNodeElementCntSum
             from NodeLevel  T1 cross apply (select Cast(SUM(T2.decNodeElementCntSumOnNode) as decimal (8, 3)) as decNodeElementCntSum
                            from NodeLevel  T2 
                            where ((T1.iIndex_Parent  <> T2.iIndex_Parent  and T2.iIndex_Parent/100 = T2.iElementID_Parent) or
                                  ( T1.iElementID_Parent = T2.iElementID_Parent))
                                  and T1.iElementID_Root = T2.iElementID_Root
                                  and T1.iElementID = T2.iElementID
                                  )a
             Where iElementID_Parent is not null                                                                          
	
	
	
	
	RETURN (@Result)
29 ноя 13, 06:47    [15209449]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Спасибо всем кто помогал! Пока на этом остановимся. Слишком много надо править еще до этого запроса, а там глядишь и вообще все иначе выглядеть будет.
29 ноя 13, 10:26    [15210207]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
LexusR
Member

Откуда: Novosibirsk
Сообщений: 1873
Изерлонер
[spoiler ]
....Если я пытаюсь подробно описать предметную область, базу данных, запросы и что мне надо задавая вопросы на форуме – всем резко становится скучно в теме никого не остается.


Подробно описывать предметную область не всегда необходимо.Если Вы сами нормально ориентируетесь в структуре своих данных то достаточно создать простейший макет данных c минимальным набором полей сохранив структуру связей (оформив всё соотвествующим образом) и описать требуемый результат на этих данных.
Тогда никому не будет скучно и Вас быстро направят на путь истиный :)
29 ноя 13, 11:44    [15210881]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
o-o
Guest
+1 к LexusR.

в след. раз выкладывайте тестовые данные и желаемый результат.
а если все равно непонятно будет, что откуда, мы спросим

Изерлонер
+

Тем, кто все же помог, даже просто советом, подсказкой я очень благодарен.
…вот на соседней ветке по Access мне очень помог "Программист-Любитель"



+
тоже хочу всем спасибо сказать.
вообще всей этой ветке форума.
хорошо, что все вы есть, от профессионалов до клоунов.

еще хочется раздать "призовые ленточки"
(щас наши офф-ы потрут )

1. знание + корректность to invm
2. мистер своебразность to Mnior
3. SQL-ниндзя to daw
(всегда по теме, всегда ценная информация, а сам появляется неожиданно ниоткуда и пропадает вникуда)

не будем тыкать пальцем, но также спасибо двум синьорам: "всегда рад послать пинком под зад в нужном направлении"
и "щас всем опишу, какое ты чмо, но так и быть, получи желанную конфетку".
что бы мы без вас делали, как ни крути, нельзя не признать, что вы всезнайки
29 ноя 13, 12:44    [15211363]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Да, можно с тестовыми данными конечно (более того уже использую Ваш совет, просто в правило это ещё не вошло). Только ведь одними данными дело не ограничивается. Что бы было понятно что необходимо в идеале нужно видеть как это выглядит на клиенте, а здесь как быть? Картинки прикладывать....
Я к чему про клиента вспомнил, многие решения они же от внешнего вида форм и контролов исходят. Где что располагается и как взаимодействует. И если изначально визуальный интерфейс не торт, то он и запросы за собой тащит монстрообразные... Как то так.
Может быть я всё с ног на голову поставил конечно... потому как вроде всё должно быть наоборот, и интерфейс на своём последнем месте.
29 ноя 13, 13:26    [15211699]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Изерлонер
Я на sql_ex.ru на первом этапе (обучающий), там решаю задачи пока с той стратегией – лишь бы решить задачу.
Долго вы там с таким подходом не протяните.
sql_ex.ru - просто шедевр, там реально учат как формализовывать задачу на языке, без всякого знания "движка". Что есть правильно.
Респект и уважуха его создателям.
Изерлонер
Не до оптимизации там пока.
В том то и ваша проблема и щасье что правильная формализация задачи прямо коррелирует с производительностью. Вам не надо думать об оптимизации, вам надо правильно задачу писать, а не лишь бы как, думал одно, а написал совсем другое.
Изерлонер
На самом деле описать коротко, емко, в двух словах какую-то обширную область, и так что бы всем сразу и все было понятно это большое искусство.
Этому и надо учится, а то так в пещере и останемся. Обезьяний большинство знает превосходно, а вот человеческий - мало кто, и ноют - тяжело мол.
Изерлонер
часто даже без всякого программирования, просто «в реале» не понятно что и из чего следует настолько все запутанно и противоречиво.
Как раз программирование показывает, что в "реале" мутотень была сказано, а правильно совершенно другое. Тяжело через призму гуманитарной лжи найти крупицы нужной информации, поправляя сказанное.
Изерлонер
Если я пытаюсь подробно описать предметную область, базу данных, запросы и что мне надо задавая вопросы на форуме – всем резко становится скучно в теме никого не остается. И я никого не осуждаю – ну кому этот гемор нужен кроме меня?
Да, тяжело когда очередной халявщик с подходом "лишь бы сделать" скидывает задачу на других.
Настоящий Человек не спрашивает конечный результат при описании предметной области, он спрашивает детали в им сделанных запросах.
Изерлонер
даже оформление у вас восхищает.
Это тоже важная часть, вы просто экономите всем кучу времени и если привыкнуть и использовать правильный стиль, вы сможете очень быстро читать смысл в запросах.
Мне приходится пользоваться форматтером для чужих запросов (хотя ни один из них не может делать до конца даже базовые основы форматирования ...)
Изерлонер
На выходе получаются однако, не те данные.
Да, там недоработка (поправил), но проблема в том что там ещё дофига надо доделывать и я прервался.
+ код
DECLARE	@iElementID_Root	Int = 6000
,	@iElementID		Int = 1
,	@iContractorID		Int = 4
DECLARE	@tab_level TABLE (
	iNodeElementID			Int
,	iElementID_Root			Int
,	iElementID_Parent		Int
,	iElementID			Int
,	decNodeElementCnt		Decimal(8,3)
,	decNodeElementCntSumOnNode	Decimal(8,3)
,	iIndex_Parent			Int
,	iIndex				Int
,	decNodeCnt			Decimal(8,3)
,	decZehNorm			Decimal(8,3)
,	iContractor			Int
)

;WITH [NodeLevel] AS (
	SELECT	ND.iElementID			AS iElementID_Root
	,	ND.iNodeElementID
	,	ND.iElementID_Parent
	,	ND.iElementID
	,	ND.decNodeElementCnt
	,	IsNull(ND.decNodeElementCnt,0)	AS decNodeElementCntSumOnNode
	FROM	dbo.tblNodeElement	ND
	WHERE	ND.iElementID_Parent IS NULL
UNION ALL
	SELECT	NL.iElementID_Root
	,	ND.iNodeElementID
	,	ND.iElementID_Parent
	,	ND.iElementID
	,	ND.decNodeElementCnt
	,	Cast(IsNull(ND.decNodeElementCnt,0)
		   * IsNull(NL.decNodeElementCnt,0) AS Decimal(8,3))
	FROM	[NodeLevel]		NL
	JOIN	dbo.tblNodeElement	ND ON ND.iElementID_Parent = NL.iElementID
	WHERE	NL.iElementID_Root = @iElementID_Root
)	INSERT	@tab_level
	SELECT	NL.iNodeElementID
	,	NL.iElementID_Root
	,	NL.iElementID_Parent
	,	NL.iElementID
	,	NL.decNodeElementCnt
	,	NL.decNodeElementCntSumOnNode
	,	IsNull(EP.iIndex,EI.iIndex)	AS iIndex_Parent	-- ?
	,	EI.iIndex
	,	Cast(IsNull(NullIf(NL.decNodeElementCntSumOnNode,0),1)
		   / IsNull(NullIf(NL.decNodeElementCnt         ,0),1) AS Decimal(8,3))	AS decNodeCnt
	,	ZN.decZehNorm
	,	ZN.iContractorID
	FROM	[NodeLevel]	NL
LEFT	JOIN	dbo.tblElement	EP ON EP.iElementID	= NL.iElementID_Parent
LEFT	JOIN	dbo.tblElement	EL ON EL.iElementID	= NL.iElementID
LEFT	JOIN	dbo.tblZehNorm	ZN ON NL.iNodeElementID	= ZN.iNodeElementID
	WHERE	NL.iElementID = @iElementID
Вы на многое не ответили:
	WHERE	S.iElementID		 = I.iElementID		-- ? @iElementID
	AND (	S.iElementID_Parent	 = I.iElementID_Parent	-- Sibling?
	 OR	S.iIndex_Parent		!= I.iIndex_Parent
	AND	S.iElementID_Parent	 = S.iIndex_Parent / 100-- ? o_O
	AND	S.iElementID_Root	 = I.iElementID_Root)	-- ? @iElementID_Root
		)	S
1. Зачем связка (S.iElementID = I.iElementID) если итак данные отфильтрованные по одному значению (@iElementID)
2. WTF? S.iIndex_Parent / 100
3. Вы так и не ответили почему фильтруется по @iElementID_Root только рекурсивная часть, а голова нет. ???
Вы не должны писать так что бы вас неправильно поняли. Оставьте ваши намётки с мусором за кадром.

Если никаких переменных нет - это группы, то и не надо фильтровать, группируйте как есть.
Изерлонер
Переменные
iElementID_Root -изделие
iElemetnID_Parent - "родительский" узел
iElementID - деталь (материал)
iContractorID - цех (он же в других таблицах поставщик, получатель и т.п. То есть данные цехов и всех контрагентов хранятся в одной таблице)
Проблема в том что как раз скуль и любое декларативное программирование предназначено для формализации предметной области. Это не асм, пишите названия колонок и таблиц в рамках предметной области.
Да среди проггеров часто попадаются те кто нифига не понимают и начинают обобщать. Если в базах встречаются таблицы с одинаковой структурой - это не значит что их надо соединять. Нафигачат уни-пупер-объекты а потом ломают головы, как достать данные из них. Хотя бы навешали бы представления на таблицы, чтоб потом легче исходники читать было.
Код в итоге должен быть практически текстом тех задания/описанием предметной области и читался "домохозяйкой".
В крайнем случае, переименовали колонки и таблицы хотя бы для нас.

Убрали бы вот эти ляпы: IsNull(ND.decNodeElementCnt,0) - зачем там NULL если подразумевается 0. Сделайте колонку NOT NULL и повесьте DEFAULT(0). Избавьте нас и себя от ненужного мусора.
Ваш "лишь бы" не работает. Буксует в море мусора. Это не конструктивно и не культурно.
Это хуже чем матом обзываться. Мат вообще намного более уместен чем это.
Изерлонер
Вообще все это дело я загоняю в табличную функцию и затем проставляю эти данные (норма расхода на цех/норма расхода на изделие) в каждой строчке норматива для каждого материала (запчасти) по изделию. ... работает медленно.
Слушайте, вы же сами пишите что не помпетентны. Давайте код, а далее мы покажем почему медленно и как правильно.
К тому же я вижу скалярку, а не inline. Это вообще грех писать их. Это просто тормоз по определению. Скалярки пушутся раз на миллион. Они не для обычных запросов.
Изерлонер
Apply применяется для расчета сумм. Ранее применял Sum(...) over (Partition by ...), но туда условия суммирования загнать сложно оказалось, да и работало еще медленнее.
Вы в мой запрос вкурили? Попытались понять? Рано ещё вам говорить что они могут или нет и что быстрее. Для того чтобы брать на себя ответственность такое говорить. Нужно взять на себя ответственность чистых тестов и всеобъемлющих вариантов. С подходом "тяп ляп" это несовместимо никак. Так что тут скорее "я пробывал, у меня не получилось", чем "давайте не надо так делать".
Это не вам лично - а тем кто не понимает, что "скурпулёзно" даёт совершенно другие результаты чем "тяп ляп".
Изерлонер
Условия суммирования это как раз те ньюансы. Задаются посредством индексов взаимозаменяемости. Т.е. какой-то узел может быть взаимозаменяем с другим узлом более новым или старым, не суть - другим. И расчитать суммарное количество деталей из-за этих ньюансов становится проблематично. Для этого введены индексы взаимозаменяемости - одинаковые для взаимозаменяемых деталей и узлов.
Вот слов много, смысла мало - а код которые это "описывает" ахтунг.
Я не вижу это в коде. Покажите это мне. Ибо слова лож - а формализованный код выводит всё на чистоту.
Изерлонер
Должно быть два значения, на деле таблица из значений по двум столбцам
Не должно! Если для всех значений @tab_level получается один и тот же результат так зачем его считать для каждой строки?!!! Это глупо и это неправильно так писать.
DISTINCT - что бы убрать эту "оплошность"? Вы что издеваетесь?
+ код
SELECT	Cast(Sum(S.NormsumContractor	AS Decimal(8,3)))	ZehNormSum
,	Cast(Sum(S.Normsum		AS Decimal(8,3)))	IzdNormSum
FROM	@tab_level	I CROSS APPLY (
	SELECT	Sum(S.decZehNorm * S.decNodeCnt)AS Normsum
	,	Sum(CASE WHEN S.iContractor = @iContractorID
		THEN S.decZehNorm * S.decNodeCnt
		ELSE 0 END)			AS NormsumContractor
	FROM	@tab_level S
	WHERE	S.iElementID		 = I.iElementID		-- ? @iElementID
	AND (	S.iElementID_Parent	 = I.iElementID_Parent	-- Sibling?
	 OR	S.iIndex_Parent		!= I.iIndex_Parent
	AND	S.iElementID_Parent	 = S.iIndex_Parent / 100-- ? o_O
	AND	S.iElementID_Root	 = I.iElementID_Root)	-- ? @iElementID_Root
		)	S

"На деле". Повторяю - так и пишите. Группировка по отфильтрованных столбцам. Тогда бы всё стразу стало понятно.
1 строка и сразу столько вопросов бы ушло.

Большая часть кода - это переливание из пустого в порожнее, слова автор сам не понимает что пишет и не умеет выражать свои мысли, запутывается в 3х соснах. Приходится вместо того что бы заняться делом хотя бы вправить этот код. Думать об оптимизации ещё рано. То что быстрее - это чисто ваши ошибки записи.

+ код
DECLARE	@iElementID_Root	Int = 6000
,	@iElementID		Int = 1
,	@iContractorID		Int = 4
DECLARE	@tab_level TABLE (
--	iNodeElementID			Int
	iElementID_Root			Int
,	iElementID_Parent		Int
,	iElementID			Int
--,	decNodeElementCnt		Decimal(8,3)
--,	decNodeElementCntSumOnNode	Decimal(8,3)
,	iIndex_Parent			Int
,	iIndex				Int
,	decNodeCnt			Decimal(8,3)
,	decZehNorm			Decimal(8,3)
,	iContractor			Int
)

;WITH [NodeLevel] AS (
	SELECT	ND.iElementID			AS iElementID_Root
	,	ND.iNodeElementID
	,	ND.iElementID_Parent
	,	ND.iElementID
	,	ND.decNodeElementCnt		AS decNodeElementCnt_Parent
	,	ND.decNodeElementCnt
	FROM	dbo.tblNodeElement	ND
	WHERE	ND.iElementID_Parent IS NULL
	WHERE	NL.iElementID	= @iElementID_Root
UNION ALL
	SELECT	NL.iElementID_Root
	,	ND.iNodeElementID
	,	ND.iElementID_Parent
	,	ND.iElementID
	,	NL.decNodeElementCnt
	,	ND.decNodeElementCnt
	FROM	[NodeLevel]		NL
	JOIN	dbo.tblNodeElement	ND ON ND.iElementID_Parent = NL.iElementID
)	INSERT	@tab_level
	SELECT
--		NL.iNodeElementID
		NL.iElementID_Root
	,	NL.iElementID_Parent
	,	NL.iElementID
--	,	NL.decNodeElementCnt
--	,	NL.decNodeElementCnt * NL.decNodeElementCnt_Parent
	,	IsNull(EP.iIndex,EI.iIndex)					AS iIndex_Parent	-- ?
	,	EI.iIndex
	,	IsNull(NL.decNodeElementCnt * NL.decNodeElementCnt_Parent,1)	AS decNodeCnt	-- ?
	,	ZN.decZehNorm
	,	ZN.iContractorID
	FROM	[NodeLevel]	NL
LEFT	JOIN	dbo.tblElement	EP ON EP.iElementID	= NL.iElementID_Parent
LEFT	JOIN	dbo.tblElement	EL ON EL.iElementID	= NL.iElementID
LEFT	JOIN	dbo.tblZehNorm	ZN ON NL.iNodeElementID	= ZN.iNodeElementID
	WHERE	NL.iElementID = @iElementID

SELECT	Cast(Sum(S.NormsumContractor	AS Decimal(8,3)))	ZehNormSum
,	Cast(Sum(S.Normsum		AS Decimal(8,3)))	IzdNormSum
FROM	@tab_level	I CROSS APPLY (
	SELECT	Sum(S.decZehNorm * S.decNodeCnt)AS Normsum
	,	Sum(CASE WHEN S.iContractor = @iContractorID
		THEN S.decZehNorm * S.decNodeCnt
		ELSE 0 END)			AS NormsumContractor
	FROM	@tab_level S
	WHERE	S.iElementID		 = I.iElementID		-- ? @iElementID
	AND (	S.iElementID_Parent	 = I.iElementID_Parent	-- Sibling?
	 OR	1 = 0)
--	 OR	S.iElementID_Root	 = I.iElementID_Root	-- ? @iElementID_Root
--	AND	S.iElementID_Parent	 = S.iIndex_Parent / 100-- ? o_O
--	AND	S.iIndex_Parent		!= I.iIndex_Parent)
		)	S
-- Как бэ
SELECT	Sum(CASE WHEN S.iContractor = @iContractorID
		THEN S.decZehNorm * S.decNodeCnt
		ELSE 0 END)			AS ZehNormSum
,	Sum(S.decZehNorm * S.decNodeCnt)	AS IzdNormSum
FROM	@tab_level	I
Убрал вещи которые вообще не влияют на задачу или для представленных вами данных.
Оставил пока промежуточную таблу, хотя она и не нужна.
Изерлонер
Я к чему про клиента вспомнил, многие решения они же от внешнего вида форм и контролов исходят. Где что располагается и как взаимодействует. И если изначально визуальный интерфейс не торт, то он и запросы за собой тащит монстрообразные... Как то так.
Булшит.
И компановку данных на клиенте тоже надо уметь делать не топорно.
Сдаётся мне бардак тут уже неподьёмный.
Скорее всего вы так и не объясните суть задачи и детали.

DECLARE	@iElementID_Root	Int = 6000
,	@iElementID		Int = 1
,	@iContractorID		Int = 4

;WITH [Parents] AS (
	SELECT	P.iElementID
	,	P.iElementID_Parent
	FROM	dbo.tblNodeElement	P
-- Если будет неправильный план (тормозить) - разкоментить
--	JOIN	dbo.tblNodeElement	E ON P.iElementID = E.iElementID_Parent
--	WHERE	E.iElementID = @iElementID
UNION ALL
	SELECT	E.iElementID
	,	P.iElementID_Parent
	FROM	[Parents]		E
	JOIN	dbo.tblNodeElement	P ON P.iElementID = E.iElementID_Parent
)
	SELECT	Sum(CASE WHEN ZN.iContractorID = @iContractorID
			THEN ZN.decZehNorm * X.decNodeCnt
			ELSE 0 END)			AS ZehNormSum
	,	Sum(ZN.decZehNorm * X.decNodeCnt)	AS IzdNormSum
	FROM	dbo.tblNodeElement	NE
	JOIN	[Parents]		NP ON NP.iElementID	= NE.iElementID_Parent
	JOIN	dbo.tblZehNorm		ZN ON NE.iNodeElementID	= ZN.iNodeElementID
--LEFT	JOIN	dbo.tblElement		EP ON EP.iElementID	= NE.iElementID_Parent
--	JOIN	dbo.tblElement		EE ON EL.iElementID	= NE.iElementID
CROSS APPLY (SELECT	
	1	--	IsNull(NL.decNodeElementCnt * NL.decNodeElementCnt_Parent,1)	-- ?
			)	X (decNodeCnt)
	WHERE	NE.iElementID = @iElementID
	AND	NP.iElementID_Parent = @iElementID_Root
И это всё равно ещё не до оптимизации. Ибо надо научится формализовывать свои мысли.

Если это табличная функция, то у вас всё равно неправильный подход.
Повторяю - надо вычислять во время изменения данных в таблице в специальную колонку, а запросом просто из неё тупо доставать.
1 дек 13, 14:05    [15220194]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Mnior,

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

оффтоп
+
Я не скрывал и не скрываю что я не специалист ... и да, действительно в базах данных не силен и ... не компетентен. Жизнь заставила этим заняться ... хотя говорить "заставила" не совсем корректно, так как это мне действительно интересно. ...Ну не получилось в свое время, либо внимания не обратил что-ли на эту область, да время к сожалению упущено... но надеюсь не совсем. Понимаете, я непосредственно базами данных занялся около года назад, а MS SQL Server в первый раз увидел ... и года с той поры нет, я надеюсь какой-то прогресс все-таки за это время есть? При том при всем учитывая сколько времени может себе позволить студент профильного ВУЗа по данной тематике, молодой и свободный человек и сколько я имея весьма нервную и напряженную работу и семью которой надо как минимум уделять внимание.

... да не чем мне гордится, не о том пишу. Жизнь такая. И подходы все от нее же. И то что бегом - лишь бы решить от туда же - катастрофическая не хватка времени. Если Вам срочно окоп вырыть надо, а у Вас лишь палка в руках - Вы же будете копать палкой и таки выроете яму, забив на то что лопатой то оно быстрее и эффективнее. Когда еще та лопата Вам в руки попадет... а надо здесь и сейчас, пользуясь тем что Вы имеете здесь и сейчас.

И если у меня нет опыта использования оконных функции, или я не знаю об Cross Apply я буду пользовать группировки в соответствии с тем образцом отложившимся в памяти - который не раз использовал, пусть даже он не эффективен, делая дикие нагромождения операторов и функций - лишь бы любым путем получить РЕЗУЛЬТАТ... до тех пор пока не изучу что-то более эффективное.

Я не знаю, может быть с Вашей точки зрения это не верный подход... но как-то вот иначе не получается.

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

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

... Знаете чем мне нравятся базы данных? Я довольно четко вижу цель. Как ближайшую, так и в средней перспективе, так и в будущем - к чему это можно и надо привести. И это очень мощный стимул.
1 дек 13, 19:50    [15221253]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Mnior
Сдаётся мне бардак тут уже неподьёмный.
Скорее всего вы так и не объясните суть задачи и детали.


Объясню. Могу подробно с постановки задачи и со схемами базы данных на текущий момент, не сразу конечно, но можно это все сюда выложить. ... но я бы не хотел тратить ни Вашего, ни моего времени с тем что бы ни к чему не прийти в конце концов. И я действительно переживаю не только за свое время, мне претит грузить кого-то всем этим ... мусором, хотя иногда и без этого никак. Мне одного Программиста-Любителя жалко было - тянул тянул меня дурака. В конце концов бросил и правильно сделал.
1 дек 13, 20:05    [15221308]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Изерлонер
мне претит грузить кого-то всем этим ... мусором, хотя иногда и без этого никак. Мне одного Программиста-Любителя жалко было - тянул тянул меня дурака. В конце концов бросил и правильно сделал.
Одного понять не могу, а вам что с этого? С одной стороны видно что эта работа вам не к лицу и вы всё вроде понимаете, но вы упорно её пытаетесь тащить и пытаетесь вкурить во всё.
Может нанять специалиста? А вы бросите эти виртуальные занятия и займитесь реальным миром?
Да и нормальные манагеры сейчас в дефиците ...
Изерлонер
Жизнь заставила этим заняться ... хотя говорить "заставила" не совсем корректно, так как это мне действительно интересно.
Хм. Знавал я одного весёлого парня. "Гуманитарий". Я чуть ли ему сразу не сказал, что профессию он не ту выбрал, ну точнее не тем в ней занимается. А он упёртый. Буксует всё на том же. Его не трогали, получает свою денежку. И цепляет его что-то, ибо одной упёртостью не объяснить всё. Жалко парня, точнее что мог бы делать больше пользы. И понять как бы заинтересовать его чем-то "другим" ...
Надеюсь вы не из таких.
Изерлонер
Когда еще та лопата Вам в руки попадет... а надо здесь и сейчас, пользуясь тем что Вы имеете здесь и сейчас.
Это проблема. И основа стратегии соц типов. Эти думают что другие нифига не добиваются, а те - что первые бегают за миражами ... как бы так до 40 не допрыгаться.
автор
пусть даже он не эффективен, делая дикие нагромождения операторов и функций - лишь бы любым путем получить РЕЗУЛЬТАТ... до тех пор пока не изучу что-то более эффективное.
Ууу. Экстраверсия. Главное галочка в конце дня. А утром опять грабли за завтрак. Ладно, шучу, шучу. Да и это врождённое, каждый будет верить в "свой" подход до последнего или депресняк/злость заест.
Просто вот к чему я клоню. Каждая стратегия имеет свою нишу хорошего применения. Хотя всё работает, что шевелится (можно и в противоположную сторону пойти и обогнуть шар). И вот когда сложность переходит некую условную границу - тогда стратегия начинает буксовать, меняться ролями. А с другой стороны "галочка" условна - одно и тоже в разной обстановке противоположны. И в итоге стоит ли оно таких усилий?!
Изерлонер
Вы столько вопросов назадавали, которые неминуемо потащат за собой и другие вопросы, что наверное проще вообще всю задачу с нуля описать
Типичный экстраверт до мозга костей (хотя я тут обычно подстраховываюсь и пишу общим "Гуманитарий"). Вы просто бежите от этих сложностей - в поле простых векторов, где цель ясна.
Мне кажется что основной совет соционистов до боли верен "Обучайте ребёнка усиленно тому, к чему у него нет врождённых предпочтений, остальное наживётся само."
Вы правы, вы необходим отличный учитель, который вас научит-натренирует всем "приёмам". Только этот чел реально крут, что может научить. Но главное - вам будет это неприятно палюбэ ибо будет всё равно выходить из "поля простых векторов". Т.е. немного насилия неизбежать.
Вот я думал вас тут попытаться "поучать", а вы убегаете.
Изерлонер
Сделаю. Более того, самые необходимые вещи уже реализованы (да не эффективно, да тормознуто, да в конце концов на текущем этапе пользоваться этим могу только я, посади кого-нибудь со стороны не сможет он наработанным функционалом пользоваться, а сможет - так выбьют его из колеи косяки возникающие то там то тут, о которых я знаю и знаю как их обойти). Лишь бы было еще время.
Вы знаете, для некоторых это страшный сон. Они даже параноят, что эти таким подходом угрохают всё. Даже вот комикс накалякали.
Упорство это хорошо, но лучше его применять к нужным вещам. К более простым, к реальным. Приструнить свои амбиции и найти место где себе меньше гемора и другим польза. И главное не тыкают.
Изерлонер
Знаете чем мне нравятся базы данных? Я довольно четко вижу цель. Как ближайшую, так и в средней перспективе, так и в будущем - к чему это можно и надо привести. И это очень мощный стимул.
Хм. Очень интересно, а можно поконкретней. Что за цель и что привести? Что такого могут БД что помогают увидеть/сделать?
Своей простотой? Досягаемостью? Ближе к реалям?
Изерлонер
выполняются для каждой строки
Что-то вы много понимаете для плохого формализатора ...
И кстати, я дотошный, тут именно что скалярки имелись ввиду. А инлайн функции, т.е. параметризованные представления таким недостатком не обладают. Главное правильно их писать, а тут без дзена никуда. В воде хорошо плавает рыба, а не топор.

Конечно определённая отрасль скорее предпочитает не все социатипы, но мне кажется что насыщенная как раз вмещает, главное не узко мыслить и не поддаваться стереотипам поведения. Строить отношения и обязанности и кто чем занимается можно по разному. И другая модель неожиданно для остальных "стрельнёт".
2 дек 13, 04:06    [15222562]     Ответить | Цитировать Сообщить модератору
 Re: Ускорить выполнение запроса.  [new]
Изерлонер
Member

Откуда: СФО
Сообщений: 1269
Mnior
Долго вы там с таким подходом не протяните.
sql_ex.ru - просто шедевр, там реально учат как формализовывать задачу на языке, без всякого знания "движка". Что есть правильно.
Респект и уважуха его создателям.

Пока тяну (заканчиваю обучающий этап), хотя бывает тяжело, да. Респект безусловно.

Mnior
Как раз программирование показывает, что в "реале" мутотень была сказано, а правильно совершенно другое. Тяжело через призму гуманитарной лжи найти крупицы нужной информации, поправляя сказанное.


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

Mnior
Да, тяжело когда очередной халявщик с подходом "лишь бы сделать" скидывает задачу на других.
Настоящий Человек не спрашивает конечный результат при описании предметной области, он спрашивает детали в им сделанных запросах.


Я надеюсь Вы не обо мне. Я как раз таки пытаюсь идти по второму пути. Спрашиваю детали в сделанных мной запросах. Просто все так запущено что приходится объяснять и изначальные условия и ход моего решения - там везде могут быть и есть ошибки. И вообще может быть такое что я спрашиваю и подразумеваю одно, те же кто отвечают, не зная ни исходных предпосылок и не понимая что нужно - решают совершенно другую задачу. Тут единственное решение наверное как здесь мне уже подсказали - сделать скрипты самой базы данных и выложить сюда, так и сделаю. И мне не нужно готового решения. Мне нужно понимать самому.

Mnior
Да, там недоработка (поправил), но проблема в том что там ещё дофига надо доделывать и я прервался.


Не спешите пожалуйста, а то получается как я уже выше заметил что мы друг друга не понимаем, да и вообще ситуация немного ушла в сторону.

Mnior
1. Зачем связка (S.iElementID = I.iElementID) если итак данные отфильтрованные по одному значению (@iElementID)

Это ошибка.

Mnior
2. WTF? S.iIndex_Parent / 100

Поясняю. База данных описыват изделия и агрегаты, состоящие из узлов, подузлов, деталей. Многие подузлы и детали могут быть взаимозаменяемыми. Ну стоял на агрегате когда-то узел А прошло время - его модифицировали - получился узел Б. Это по составу и по количеству деталей уже разные узлы. Но в ремонт может прийти как агрегат с узлом А, так и с Б. Как определить конкретное количество конкретных деталей стоящих на изделии (в нормативах, В ПЛАНЕ а не в факте!) если оно может прийти в той или другой комплектации. Забивать все возможные комплектации - увольте, и так гемора хватает. Да и не решает это ничего. Вообще с этой взаимозаменяемостью беда. Задал вопрос здесь на форуме мне посоветовали довольно интересное, хотя может и не бесспорное, решение. В таблицу элементов (детали, агрегаты, изделия, материалы - тупо справочник всех возможных элементов) вводится поле iIndex основная задача которого как раз определение взаимозаменяемости. Я не знаю, может Akina имел ввиду не совсем то что я сделал, дальнейшая проработка уже моя, за эту идею ухватился. Ввел для себя понятие базовой детали и базовой комплектации - это какая-то конкретная комплектация и деталь принимаемая для агрегата по умолчанию. Для нее и расчитываются все нормы и количества деталей. Но так как в нормативах желательно указывать и взаимозаменяемые узлы и элементы, то для каждого такого элемента в запросе расчитывается количества и нормы расхода деталей так как если бы стоял этот один (ну или сколько их там данной конкретной номенклатуры) этот заменяющий узел, а все остальное принимается как по базовой комплектации.
В чем все это выразилось. В таблицу элементов введено поле iIndex. По умолчанию iIndex = iElementID * 100 (вот откуда это WTF! это проверка на то является ли узел базовым или заменяющим базовый!). Для того что бы задать взаимозаменяемость узлов, для нескольких взаимозаменяемых узлов определяется базовый и его iIndex присваивается всем остальным узлам (это все, понятное дело, вручную происходит, пока тупо в табличной форме. Соответственно если выполняется равенство S.iIndex_Parent / 100 = iElementID_Parent - это дает указание что узел является базовым, и расчет деталей здесь происходит по общему правилу. Если же равенство не верно - это узел заменяющий, и расчет количества деталей и норм здесь происходит несколько по другому.

Mnior
3. Вы так и не ответили почему фильтруется по @iElementID_Root только рекурсивная часть, а голова нет. ???

По всей видимости тоже ошибка, хотя выдавало вроде верные данные.

Mnior
Вы не должны писать так что бы вас неправильно поняли. Оставьте ваши намётки с мусором за кадром.

Стараюсь. Опять же проще наверное будет скриптов наделать с базы и выкладывать, тогда может быть и понятнее будет.


Mnior
Да среди проггеров часто попадаются те кто нифига не понимают и начинают обобщать. Если в базах встречаются таблицы с одинаковой структурой - это не значит что их надо соединять. Нафигачат уни-пупер-объекты а потом ломают головы, как достать данные из них.


Я тут довольно жестко привязан к старой базе складского учета сделанной в 90-х еще под ДОС. Используется она на предприятии весьма активно. ....Вообще база ужасная я полтора года башку ломал пока разобрался что и как там работает. Подход взял из нее. И мне кажется это довольно удобно. Зачем мне отдельные таблицы поставщиков, клиентов, и подразделений если все это имеет фактически одну структуру, да и в той базе это уже сделано так и я не могу на это повлиять? С тем что бы доставать нужные данные проблем не возникало.
Или зачем мне разделять например таблицу элементов отдельно на таблицу материалов, отдельно на запчасти, если достаточно просто признак ввести, группы и подгруппы для определения что это такое.


Mnior
Убрали бы вот эти ляпы: IsNull(ND.decNodeElementCnt,0) - зачем там NULL если подразумевается 0. Сделайте колонку NOT NULL и повесьте DEFAULT(0). Избавьте нас и себя от ненужного мусора.

Сделаю.

Mnior
Ваш "лишь бы" не работает. Буксует в море мусора. Это не конструктивно и не культурно.


Поймите, это не "лишь бы", Вы не с тем человеком разговариваете - а тяп ляп - и так сойдет. Я хочу что бы у меня все было красиво, доступно и понятно. Но когда горит - надо пожар тушить, а не о красоте думать. А вот когда пожар потушу, можно будет спокойно и порядок навести (если дадут).

Mnior
Вы в мой запрос вкурили? Попытались понять?

Конечно. Ну я же не просто так эту тему открыл что бы болтологией заниматься. Я читаю и пытаюсь разобраться в Ваших запросах.

Mnior
Не должно! Если для всех значений @tab_level получается один и тот же результат так зачем его считать для каждой строки?!!! Это глупо и это неправильно так писать.
DISTINCT - что бы убрать эту "оплошность"? Вы что издеваетесь?


Не издеваюсь, собственно оно так и есть расчет для каждой строки (поправлюсь только - для каждой строки с означенными критериями - конкретный iElementID, iElementID_Root, iContractorID для других значений этих параметров и на выходе другие значения будут) Вот это как раз идет от реализации на клиенте, от того как там это выглядит и для чего именно так. Я просто не знаю как можно сделать по другому и можно ли. Может быть Вы посоветуете?
Суть.
Через бухгалтерию (матгруппа) списываются со склада запчасти и материалы на ремонт изделий. Документально это "требования" на списание. В требовании указывается изделие ремонт которого осуществляется, подразделение (цех) который выписывает данные детали/материалы, перечень деталей/материалов с их количествами, цены, счета фактуры и прочая лабуда.
Моя задача - сверить номенклатуру списываемых деталей/материалов и их количества с нормативным.
Как это сделать наглядно и что бы все было сразу видно?
У меня сделано следующим образом. По выбору "требования" на экран выдается его состав - что конкретно было списано.
В КАЖДОЙ строке "требования" помимо того количества материалов/запчастей которое прописано в требовании проставляется сколько вообще было списано данного материала/запчасти на это изделие в данном конкретном цехе. Две суммы с группировкой по изделию, и с группировкой по изделию и цеху. Это ФАКТ.
Так же в КАЖДОЙ строке требования вычисляется сумма по нормативу - сколько положено на ремонт данного изделия этой запчасти/материала. Это ПЛАН.
Далее идет условное форматирование и выделение цветом соответствующих ячеек при переборе, недоборе, выборе всей нормы. Оператор сразу видит что было списано в соответствии с нормативами, а что помимо.
Ну как еще сделать что бы для каждой строки этого гребаного требования были видны суммы и проводилось сравнение без дополнительных действий оператора? Что бы одним взглядом определить что не так?

К сообщению приложен файл. Размер - 139Kb
2 дек 13, 04:41    [15222583]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2 3 4 5   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить