powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Best practice по сведению двух CTE
98 сообщений из 98, показаны все 4 страниц
Best practice по сведению двух CTE
    #39563317
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спецы, поделитесь пожалуйста best practice.

Имеется CTE собраный из нескольких селектов.
Требуется сделать выборку из этого CTE с урезанным набором полей (соотвественно схлопнутся записи), добавить к этому одно поле (нацепить на каждую запись некое вычисление) и приджойнить добавленное поле обратно к изначальному CTE.

Что посоветуете? Вью? Табличную функцию? Может можно как-то вложить CTE в CTE ? Etc...?

Спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563335
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут еще друидский круг нужен, как без него CTE в CTE вкладывать-то?...

З.Ы. Берете и делаете
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563336
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetМожет можно как-то вложить CTE в CTE ? Etc...?Через запятую. Посмотрите справку с примерами по CTE
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563338
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей Алексеевич,

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

К чему это глумление?

Заранее спасибо за конструктивную помощь.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563340
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexeyvg,

Спасибо, посмотрю. Раньше что-то не нагуглилось такое.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563344
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetalexeyvg,

Спасибо, посмотрю. Раньше что-то не нагуглилось такое.Лучше справку смотреть, а не гуглить (хотя справка у МС ухудшается с каждым годом).
Просто после определения CTE ставите запятую, и пишите новое определение CTE, в котором можно использовать предыдущее (все предыдущие).

Пример из справки "C. Using multiple CTE definitions in a single query"
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
WITH Sales_CTE (SalesPersonID, TotalSales, SalesYear)  
AS  
-- Define the first CTE query.  
(  
    SELECT SalesPersonID, SUM(TotalDue) AS TotalSales, YEAR(OrderDate) AS SalesYear  
    FROM Sales.SalesOrderHeader  
    WHERE SalesPersonID IS NOT NULL  
       GROUP BY SalesPersonID, YEAR(OrderDate)  
  
)  
,   -- Use a comma to separate multiple CTE definitions.  
  
-- Define the second CTE query, which returns sales quota data by year for each sales person.  
Sales_Quota_CTE (BusinessEntityID, SalesQuota, SalesQuotaYear)  
AS  
(  
       SELECT BusinessEntityID, SUM(SalesQuota)AS SalesQuota, YEAR(QuotaDate) AS SalesQuotaYear  
       FROM Sales.SalesPersonQuotaHistory  
       GROUP BY BusinessEntityID, YEAR(QuotaDate)  
)  
  
-- Define the outer query by referencing columns from both CTEs.  
SELECT SalesPersonID  
  , SalesYear  
  , FORMAT(TotalSales,'C','en-us') AS TotalSales  
  , SalesQuotaYear  
  , FORMAT (SalesQuota,'C','en-us') AS SalesQuota  
  , FORMAT (TotalSales -SalesQuota, 'C','en-us') AS Amt_Above_or_Below_Quota  
FROM Sales_CTE  
JOIN Sales_Quota_CTE ON Sales_Quota_CTE.BusinessEntityID = Sales_CTE.SalesPersonID  
                    AND Sales_CTE.SalesYear = Sales_Quota_CTE.SalesQuotaYear  
ORDER BY SalesPersonID, SalesYear;  
GO
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563347
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexeyvg,

Моя задача чуть сложнее. Мне нужно второй CTE селектить из результата первого.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563352
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, увидел. Обращение к первому CTE тоже работает.

Огромное спасибо! Это то что искал.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563388
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetК чему это глумление?

Заранее спасибо за конструктивную помощь."Мне надо забить гвоздь. Что посоветуете? Бить правой рукой? Бить с разбега? Или повыше прыгнуть? Может как-то можно гвоздь молотком забить? Вот мне понадобилось решить задачу, которой обычно не занимаюсь. Причём не прошу сделать это за меня. Прошу описать в паре предложений как обычно такие вопросы решаются.".

Вам самому не смешно? Уж простите, в ответе не больше глумления, чем вы своим вопросом продемонстрировали. В справке все уже давно с примерами расписано.

Заранее спасибо за адекватные вопросы.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563392
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей Алексеевич,

Клоунада не делает Вам чести.

Забивание гвоздя - операция простая, интуитивная, в один цикл.
Мне надо было произвести операцию в несколько циклов, один из которых пользуется результатом предыдущего. Никак с забиванием гвоздя не сравнить.
Для незнакомой среды - нетривиально. Потратил несколько часов на попытку самостоятельного решения.

Уважаемый alexeyvg счёл мой вопрос адекватным - и помог. Спасибо ему.

Вы же предпочли глумиться.

Нет, мне не жалко, наздоровье. Главное, получил ответ на свой вопрос.
Да и Вас воспитывать не претендую - поди взрослый дядя.
Спасибо что модерируете этот форум.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563395
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetУважаемый alexeyvg счёл мой вопрос адекватным - и помог. Спасибо ему.Уважаемый alexeyvg -- поблагодарим же его за терпение -- вам перепечатал хелп синтаксиса.
slovnetЗабивание гвоздя - операция простая, интуитивная, в один цикл.
Мне надо было произвести операцию в несколько циклов, один из которых пользуется результатом предыдущего. Никак с забиванием гвоздя не сравнить.
Для незнакомой среды - нетривиально. Потратил несколько часов на попытку самостоятельного решения.
Т.е за два часа не смогли найти и осилить примеры к синтаксису, который гуглится за 30 секунд. Если это нетривиально, то у меня для вас плохие новости, ага.

Спасибо за интересный вопрос (два).
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563425
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetЗабивание гвоздя - операция простая, интуитивная, в один цикл.
Мне надо было произвести операцию в несколько циклов, один из которых пользуется результатом предыдущего. Никак с забиванием гвоздя не сравнить.
Для незнакомой среды - нетривиально. Потратил несколько часов на попытку самостоятельного решения.А вы не гуглите, не надо, по отдельным командам это точно непродуктивно.
Возникла задача, тем более конкретно с командой CTE, так читайте сразу в хелпе, с примерами. Это точно бы не заняло несколько часов.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563467
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexeyvg,

Спасибо за совет насчёт хелп vs гугл. Буду знать.

Я видел этот хелп. И делал такое не раз. Но это пример обычного CTE.
А мне надо было результат уже сведённых таблиц отфильтровать дистинктом по части полей и нацепить на него нарастающий итог.
Такого примера в хелпе нет. Не пришло в голову что можно тупо выбрать из предыдущей таблицы CTE.
Пытался сложить CTE во вью и приджойнить к нему ещё один CTE, но понимал что это неправильный ход. Поэтому здесь спросил.

Ещё раз спасибо, ваша помощь это как раз пример того как можно потратив 5 минут сэкономить другому пару часов поисков.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563469
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

точно в хедп смотрели?

https://docs.microsoft.com/en-us/sql/t-sql/queries/with-common-table-expression-transact-sql

C. Using multiple CTE definitions in a single query
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563478
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей Алексеевич,

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

Спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563481
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563486
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гавриленко Сергей Алексеевич,

при всём (огромном) уважении, зря Вы так сегодня.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563492
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Спасибо.

Я читал этот хелп. И сейчас ещё раз посмотрел.
Этого недостаточно было для решения моей задачи.
Я делал как в этом примере, до того как сдесь спросил. Этого давало декартово произведение. И дистинкт тут не поможет.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563495
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

И как эта ссылка даёт ответ на поставленный вопрос.
Вы первое сообщение читали?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563496
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

авторЭтого давало декартово произведение.
что-то всё хуже и хуже.. cte само вам умножало? жестокая штука....

*сдесь :)
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563507
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемый TaPaK,

Вы первое сообщение читали? Я прямо там всё объяснил.

В CTE да, умножаются строки, мне именно так и надо.
Но нарастающий итог надо нацепить на схлопнутую выборку, по урезанному количеству полей.
То есть надо взять результат готового CTE, сделать по нему дистинкт по части полей, потом в этой уже схлопнутой выборке добавить ROW_NUMBER() OVER (PARTITION BY... и к этому прицепить нарастающий итог а потом приджойнить результат к изначальной умноженной выборке.

Есть такой пример в хелпе?

P.S. *сдесь - опечатка, печатаю транслитом.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563509
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

авторТо есть надо взять результат готового CTE да в хелпе есть пример использования как минимум двух результатов cte
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563520
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Ну вот и ткните меня носом в синтаксис который решит именно эту задачу.

P.S.
Надо понимать, насчёт умножения записей уже не так плохо и жёстко?
И почему приведенный Вами раньше пример не подходит тоже разобрались?

P.P.S
Мне ж не жалко, пусть мне покажут что не умею читать хелп и покажут где именно пропустил нужное.
Только спасибо скажу. Век живи..
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563524
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

на вопрос как использовать результат cte в другом хелп отвечает? при чём здесь ваши извращённые желания умножать делить и тп к синтаксису и bol????
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563540
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Как использовать результат cte внутри другого cte?
Не нашёл там.
Пожалуйста, укажите литеру примера.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563549
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetTaPaK,

Как использовать результат cte внутри другого cte?
Не нашёл там.
Пожалуйста, укажите литеру примера.
Да хорош уже, какой пример когда там черным по белому вначале написано:

A CTE can reference itself and previously defined CTEs in the same WITH clause. Forward referencing is not allowed.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563552
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

Вы можете сылаться внутри СТЕ на другие СТЕ того же блока with как если бы это были внешние таблицы:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
create table #T1(C1 decimal(6,2), C2 varchar(20))
insert #T1 values(1,'one'),(2,'two'),(3,'three'),(4,'four'),(5,'five')

;with 
Q0 as
(
 select * from #T1
)
,
Q2 as
(
  select top 3 * from Q0 order by c1 desc
)
,
Q3 as
(
  select top 1 * from Q2 order by C1
)
select * from Q3
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563555
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

О! Первое конструктивное замечание. Спасибо!
А теперь всё же если не затруднит, пример синтаксиса. Поскольку там такого примера нет.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563560
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetCammomile,

О! Первое конструктивное замечание. Спасибо!
А теперь всё же если не затруднит, пример синтаксиса. Поскольку там такого примера нет.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
;WITH  FirstCTE 
AS 
  (
  SELECT N =  1 
  )
,SecondCTE  
AS 
  (
  SELECT 
    N = F.N + 41 
  FROM FirstCTE F

)
SELECT TheAnswerIs =  N FROM SecondCTE
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563561
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us,

Спасибо!
Это именно то что вчера сделал.
То есть изначально искал несколько другое решение, но именно приведенный Вами синтаксис решил мою задачу.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563569
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

Спасибо.
Видите как просто было помочь человеку. Сколько воды зря перемолотили здесь (не имею в виду именно Вас).
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563579
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

может Вам это сейчас не надо, но так, просто для информации на будущее:
есть ещё и другой тип применеия/построения CTP: рекурсивные CTP - для работы с иерархическими данными.

Там изнутри CTP ссылаются на сам CTP.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563589
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Us,

Спасибо.
Надо будет почитать повнимательней.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563606
Шыфл
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 ALL
Человек спросил про запятую, а его 50 постов ногами пинают...

Грамматика SQL вещь сложная, что уж говорить о пунктуации...

2 TS

Есть ещё удобная вещь - присоединение Outer Apply - не так давно, после 10 лет практики в SQL открыл для себя её заново. Когда нужно "добавить к этому одно поле (нацепить на каждую запись некое вычисление)" - это то, что доктор прописал
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563611
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шыфл,

Спасибо.
Впрочем, я не студент, на пинания не обижаюсь. От них только профит, ещё несколько раз проштудировал примеры в хелпе.

Да, Outer Apply я использую, но в чистом виде оно мне было недостаточно.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563618
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet,

а чего же в APPLY вам не хватило то?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563630
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Дак вроде уж Вам лично объяснил про схлопывание записей?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563637
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetTaPaK,

Дак вроде уж Вам лично объяснил про схлопывание записей?
вы не можете засунуть DISTINCT в OUTER APPLY?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563638
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дорогие специалисты MSSQL!
Спасибо вам всем, ответившим в этой ветке.
И помогавшим, и критиковавшим - спасибо.
Благодаря вам новичок в MSSQL не только нашёл решение конкретной задачи, но и узнал много нового о CTE и вообще.

Приходите ещё в мои ветки, у меня очевидно будет ещё много вопросов.

Ифчо, задача решена ещё вчера, но если ещё кому надо "попинать студента", налетай, обслужу :)
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563645
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я вот сижу, и думаю.

Ежели я в инлайн функции объявил несколько ОТВ, притом, эти ОТВ, скажем так "справочники" (датасет детерменирован)
Типа
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
 
;WITH Types AS
(
SELECT Type =  10001  
UNION
SELECT Type =  10002  
UNION
SELECT Type =  10003
) 




И эту инлайн функцию я накидываю на какой-то селект, серва догадается, что эти ОТВ на каждую строку входного запроса вернут один и тот же датасет и закеширует, или как дурак будет делать рассчеты стопицот миллионов раз?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563657
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

С этого места, пожалуйста, поподробней.
Где в этом коде вставлять дистинкт?

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
WITH 
t AS (
  SELECT
     PartName, Ordname, Date, Qnt, WorkOrder
     [rn] = ROW_NUMBER() OVER (PARTITION BY [PartName] ORDER BY [date)
)
SELECT
  *
FROM
  t t1
  OUTER APPLY (
     SELECT
       [AllocatedQnt] = SUM(Qnt)
     FROM
        t t2
     WHERE
       t2.[PartName] = t1.[PartName]
       AND t2.[rn] <= t1.[rn]
  ) alloc



А если выборка t включает размноженные строки с разными нумераторами rn, поскольку на каждый Ordname есть несколько WorkOrder's, а нарастающий итог надо посчитать по заказам?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563658
iap
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

Просто написать инлайн функцию и надеяться, что она сама собой станет детерминированной, недостаточно.
Как минимум надо объявить её SCHEMABINDING
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563680
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile

авторИ эту инлайн функцию я накидываю на какой-то селект, серва догадается, что эти ОТВ на каждую строку входного запроса вернут один и тот же датасет и закеширует, или как дурак будет делать рассчеты стопицот миллионов раз?

инлайн функция не вычисляетя "каждый раз", отдаёт план аналогичный обычному представлению.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563868
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
TaPaK,

Мне правда интересно насчёт DISTINCT в OUTER APPLY.
Отпишитесь пожалуйста по моему примеру. 21004192
Может там правда можно было какой DISTINCT засунуть и код укоротить?

Заранее спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563882
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetМожет там правда можно было какой DISTINCT засунуть и код укоротить?
А версия сервера у вас какая? А то и правда ваш код можно покороче переписать.
Присутствие DISTINCT в коде, если это не для быстро посмотреть, какие вообще значения (сочетания) есть, - моветон.

slovnetА если выборка t включает размноженные строки с разными нумераторами rn, поскольку на каждый Ordname есть несколько WorkOrder's, а нарастающий итог надо посчитать по заказам?
*картинка WHAAT?!*
Вы сами-то понимаете, чего вы хотите? "Рисуйте" в excel исходные данные и конечный результат. А гадать по вашим скриптам (которые вы кстати предоставили спустя 5 постов) наши местные телепаты устают.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563907
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Руслан ДамировичslovnetМожет там правда можно было какой DISTINCT засунуть и код укоротить?
А версия сервера у вас какая? А то и правда ваш код можно покороче переписать.
Microsoft SQL Server 2008 R2 (SP2) - 10.50.4042.0 (X64) Mar 26 2015 21:18:04 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.2 <X64> (Build 9200: ) (Hypervisor)

По Вашему же совету этот код и использовал в 2008.

Руслан ДамировичПрисутствие DISTINCT в коде, если это не для быстро посмотреть, какие вообще значения (сочетания) есть, - моветон.

Знаю. Как говориться, необходимо но недостаточно.
Руслан ДамировичslovnetА если выборка t включает размноженные строки с разными нумераторами rn, поскольку на каждый Ordname есть несколько WorkOrder's, а нарастающий итог надо посчитать по заказам?
*картинка WHAAT?!*
Вы сами-то понимаете, чего вы хотите? "Рисуйте" в excel исходные данные и конечный результат. А гадать по вашим скриптам (которые вы кстати предоставили спустя 5 постов) наши местные телепаты устают.

Я очень хорошо понимаю что хочу. И много раз здесь объяснял, включая исходный пост.
У меня конечный результат уже "нарисован" в Results а не в excel .
Гадать не надо, сразу объяснил. Могу ещё объяснить если вдруг надо.

Скрипт, мной предоставленный - он не мой, а Ваш (с моими косметическими изменениями) предоставленный мне в посте 20989369 :)
За что Вам ещё раз отдельное спасибо.
Здесь же я его привёл просто для иллюстрации TaPaK о том что DISTINCT не поможет.

P.S. Шож тут гуру такие нервные...
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563919
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот знаешь, товарищ, совет тебе на будущее.
Чтобы местные гуру и не гуру были более дружелюбными, делай ЗАРАНЕЕ воспроизводимое репро. А не пиши словами свои хотелки.
Все скуль задачи решаются на абстрактном уровне, очень редко решение зависит от физических данных.


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

Посмотри пример нормально оформленного вопроса.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563920
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetИ много раз здесь объяснял, включая исходный пост.
Скрипт, мной предоставленный - он не мой, а Ваш (с моими косметическими изменениями) предоставленный мне в посте
У меня конечный результат уже "нарисован" в Results а не в excel
Сопоставлять ваше имя и ваш вопрос с каким-то другим постом, в котором вам уже дали исчерпывающий ответ (да еще и я)?
slovnetЯ очень хорошо понимаю что хочу.
Не понимаете, или хотите совсем не того, что вываливаете в первом посте. Склоняюсь к тому, что вы просто хотите не думать, а получить ответ, ну или устали, потому что тема тяжелая.
slovnetP.S. Шож тут гуру такие нервные...Так мы тоже не железные. То приходится таблички из картинок извлекать, то скрипты, то угадывать, что автор хотел/сказать, вытягивая из него информацию так, чтобы не обидеть.

А теперь давайте сделаем ребут.
Вы выложите данные еще раз. Еще раз нарисуете результат. И скрипт, который что-то там делает, но этого результата не дает. А уж мы постараемся помочь.
Это конструктивнее, чем выяснять, кто прав, а кто злой.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563932
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

ОК. Спасибо.
Просто код на деле больно громоздкий там, много очень сводных выборок из разных баз.

Но на будущее буду знать. Хотя вот рядом товарищ утверждает что по скриптам гадать не будут, надо пример результата в екселе, говорит, рисовать.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563938
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну ты же можешь упростить до вменяемого уровня!

Нафига нам проникать мозгом твои сложные структуры, когла концептуально вопрос о том, как юзать ссылки цте на цте и аплаи?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563962
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Руслан Дамирович,
Во первых, спасибо за конструктивное предложение и за желание помочь.
Нет, тут никто не злой и все правы:) Только нервные немного. Ну да, никто не железный, и я тоже:)
Тяжело отвечать каждый раз новому гуру на те же упрёки :) Только одному всё объяснишь, следующий появляется.
Но это хорошо - мощный траффик гуру детектед.

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

3. Прекрасно понимаю что хочу. Думал достаточно.

4. Код готов ещё вчера и выдаёт именно тот результат что требовался.

5. В рамках проявления доброй воли и попытки выяснить для себя насчёт DISTINCT в OUTER APPLY чуть позже постараюсь запостить пример Input/Output + скриптик.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563964
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileНу ты же можешь упростить до вменяемого уровня!

Нафига нам проникать мозгом твои сложные структуры, когла концептуально вопрос о том, как юзать ссылки цте на цте и аплаи?

Прав совершенно. Учту на будущее.
Понял что на этом не стоит экономить время.
Спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563971
Руслан Дамирович
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet4. Код готов ещё вчера и выдаёт именно тот результат что требовался.
Мы так и поняли, что ты хочешь узнать, а можно ли сделать лучше (быстрее/удобнее/нагляднее). Но твой вопрос в первом посте был слишком абстрактным, чтобы ответить на него адекватно. Потому и начали слегка подначивать. Ты-таки раздуплился на кое-какой код, но без данных - никто не будет пытаться его улучшить, так как он и так работает.

А твой вопрос о том, что нужен нарастающий итог по заказу, а не по деталям заказа - вообще не имеет смысла с моей точки зрения. Потому и попросил исходные данные и результат, чтобы понять, что именно ты хотел этим сказать.
Так что ждем портянку
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563983
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По предложению уважаемых комрадов формулирую вопрос правильно:
Input:

OrdNo Date PartName OrdQtyЗаказ1 01/02/18 Part1 5Заказ2 01/01/18 Part1 8Заказ3 01/05/18 Part1 3Заказ4 01/01/17 Part2 10Заказ5 01/01/19 Part2 6

OrdNo WorkOrderЗаказ1 WO1Заказ1 WO2Заказ2 WO3Заказ2 WO4Заказ3 WO5


PartName BalancePart1 20Part2 29

Надо выдать все заказы (OrdNo), Date, PartName, OrdQty, Balance с распределением остатков по заказам с сортировкой по дате + ЗаказНаПроизводство (WorkOrder) привязанный к заказу.
Соответсвенно заказы 4 и 5 выпадают, а заказы 1 и 2 выдают по две записи (поскольку на каждый есть по 2 WorkOrder)
Однако распределением остатков надо произвести на уровне заказа, без разбивки по WorkOrder.

Требуемый результат выборки:
OrdNo Date PartName OrdQty AllocatedOrdQty AllocatedBalance TotalBalance WorkOrderЗаказ2 01/01/18 Part1 8 8 20 20 WO3Заказ2 01/01/18 Part1 8 8 20 20 WO3Заказ1 01/02/18 Part1 5 13 12 20 WO1Заказ1 01/02/18 Part1 5 13 12 20 WO2Заказ3 01/05/18 Part1 3 16 7 20 WO5

Скрипт в следующем посте.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563987
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Руслан Дамирович,
Раздуплился как только попросили. Уже даю. Пару минут, надо выкинуть лишнее.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39563991
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну почему не так то?!

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
DECLARE 
  @Orders TABLE (
  OrdNo varchar(20) 
, Date datetime
, PartName varchar(20) 
, OrdQty int) 

INSERT INTO @Orders VALUES 

('Заказ1',	'01/02/18',	'Part1',	5)
,('Заказ2',	'01/01/18',	'Part1',	8)
,('Заказ3',	'01/05/18',	'Part1',	3)
,('Заказ4',	'01/01/17',	'Part2',	10)
,('Заказ5',	'01/01/19',	'Part2',	6)
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564001
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
[src][/SRC]
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564002
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Либо я к концу дня деревянный, либо у тебя "желаемый результат" неправильно сделан, но насколько я понял текстовую постановку задачи, там вообще нет никаких СТЕ и аплаев.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
DECLARE 
  @Orders TABLE (
  OrdNo varchar(20) 
, Date datetime
, PartName varchar(20) 
, OrdQty int) 

INSERT INTO @Orders VALUES 

('Заказ1',	'01/02/18',	'Part1',	5)
,('Заказ2',	'01/01/18',	'Part1',	8)
,('Заказ3',	'01/05/18',	'Part1',	3)
,('Заказ4',	'01/01/17',	'Part2',	10)
,('Заказ5',	'01/01/19',	'Part2',	6)

DECLARE @Balance TABLE (PartName varchar(20), Balance int ) 
INSERT INTO @Balance  VALUES 
('Part1',	20)
,('Part2', 29)

DECLARE @Work TABLE (OrdNo varchar(20), WorkOrder varchar(20) )
INSERT INTO @Work VALUES 

('Заказ1',	'WO1')
,('Заказ1',	'WO2')
,('Заказ2',	'WO3')
,('Заказ2',	'WO4')
,('Заказ3',	'WO5')



SELECT 
  O.OrdNo  
, O.Date  
, O.PartName 
, O.OrdQty  
, B.Balance
, PartsReserved =  SUM(O.OrdQty) OVER (PARTITION BY O.PartName ORDER BY O.Date ROWS   unbounded preceding )
, PartsRest = B.Balance - (SUM(O.OrdQty) OVER (PARTITION BY O.PartName ORDER BY O.Date ROWS   unbounded preceding ))
, W.WorkOrder
 FROM @Orders O 
INNER JOIN  @Balance B ON B.PartName = O.PartName
INNER JOIN @Work W ON W.OrdNo = O.OrdNo
 ORDER BY O.Date, O.OrdNo, W.WorkOrder 

 
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564003
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Отдельно непонятно зачем тут вообще сортировка по WorkOrder когда за ним ничего не стоит.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564006
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Обещаный код.
Надеюсь что не накосячил, пришлось сильно упрощать структуру и названия таблиц/полей.
Не факт что исполнится как есть:)

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
WITH 
Orders
as
(
SELECT ORDERS.Ordname Ordname, PART.PartName PartName, ORDERS.OrdQuant OrdQuant, 
SERIAL.WorkOrder WorkOrder, ORDERS.Date Date
FROM ORDERS JOIN PART
ON ORDERS.PART = PART.PART
JOIN SERIAL  
ON (ORDERS.SERIAL = SERIAL.SERIAL AND ORDERS.PART = SERIAL.PART)
WHERE ORDERS.CLOSED <> 'C'
)
,
PartBalance
as
(
SELECT PART.PartName PartName, WARHSBAL.BALANCE Balance
FROM WARHSBAL JOIN PART
ON WARHSBAL.PART = PART.PART
WHERE WARHSBAL.BALANCE > 0
)
,
OrdsDistinctTmp as 
(
SELECT distinct Ordname, PartName, OrdQuant, Date FROM Orders
)
,
OrdsDistinct as 
(
SELECT distinct Ordname, PartName, OrdQuant, Date, 
(ROW_NUMBER() OVER (PARTITION BY PartName ORDER BY Date)) as rn
FROM OrdsDistinctTmp
)
SELECT 
	OrdsDistinct1.PartName, OrdsDistinct1.Date, OrdsDistinct1.Ordname, OrdsDistinct1.OrdQuant, AllocatedOrdQty,
	ISNULL(Balance, 0) as TotalBalance, (ISNULL(Balance, 0)-AllocatedOrdQty) as AllocatedBalance, Orders.WorkOrder
FROM
  OrdsDistinct OrdsDistinct1
  Full Outer Join Orders
	ON OrdsDistinct1.Ordname = Orders.Ordname
  Left Join PartBalance
  ON PartBalance.PartName = OrdsDistinct1.PartName
	OUTER APPLY (
     SELECT
       SUM(OrdQuant) as AllocatedOrdQty
     FROM
        OrdsDistinct OrdsDistinct2
     WHERE
       OrdsDistinct2.PartName = OrdsDistinct1.PartName
       AND OrdsDistinct2.rn <= OrdsDistinct1.rn         
       ) as alloc
       Order By OrdsDistinct1.PartName, OrdsDistinct1.Date   
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564007
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileОтдельно непонятно зачем тут вообще сортировка по WorkOrder когда за ним ничего не стоит.

Вроде про сортировку по WorkOrder нигде в условиях не упоминалось.
Но сам WorkOrder юзер хочет видеть.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564008
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileНу почему не так то?!

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
DECLARE 
  @Orders TABLE (
  OrdNo varchar(20) 
, Date datetime
, PartName varchar(20) 
, OrdQty int) 

INSERT INTO @Orders VALUES 

('Заказ1',	'01/02/18',	'Part1',	5)
,('Заказ2',	'01/01/18',	'Part1',	8)
,('Заказ3',	'01/05/18',	'Part1',	3)
,('Заказ4',	'01/01/17',	'Part2',	10)
,('Заказ5',	'01/01/19',	'Part2',	6)



Понял, ну, в следующий раз. Хотел как красивше.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564017
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

Вот именно если сделать так то на каждую запись по Ordname где 2 WorkOrder'a будет удвоен нарастающий итог.
Должно быть так:
OrdNo Date PartName OrdQty AllocatedOrdQty AllocatedBalance TotalBalance WorkOrderЗаказ2 01/01/18 Part1 8 8 20 20 WO3Заказ2 01/01/18 Part1 8 8 20 20 WO3Заказ1 01/02/18 Part1 5 13 12 20 WO1Заказ1 01/02/18 Part1 5 13 12 20 WO2Заказ3 01/05/18 Part1 3 16 7 20 WO5
А будет так:
OrdNo Date PartName OrdQty AllocatedOrdQty AllocatedBalance TotalBalance WorkOrderЗаказ2 01/01/18 Part1 8 8 20 20 WO3Заказ2 01/01/18 Part1 8 16 12 20 WO3Заказ1 01/02/18 Part1 5 21 4 20 WO1Заказ1 01/02/18 Part1 5 26 -1 20 WO2Заказ3 01/05/18 Part1 3 29 -6 20 WO5

С подбивкой баланса в это время суток мог ошибиться, но смысл ясен.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564029
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну убери тогда джойн на воркинг ордерс. Вместо него напиши вере ордернум ин...

Рассчитай набегающий итог без ордеров, а потом уже помнож на них.

Все ещё без цте и аплаев.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564087
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

А, у меня 2008.
unbounded preceding не сработает.
Забыл что пробовал уже.

"Рассчитай набегающий итог без ордеров, а потом уже помнож" это ж выходим обратно на CTE, или лыжи не едут?
Ну типа свести там все выборки.

Да и для APPLY надо в CTE подготовить ROW_NUMBER?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564088
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
DECLARE 
  @Orders TABLE (
  OrdNo varchar(20) 
, Date datetime
, PartName varchar(20) 
, OrdQty int) 

INSERT INTO @Orders VALUES 

('Заказ1',	'01/02/18',	'Part1',	5)
,('Заказ2',	'01/01/18',	'Part1',	8)
,('Заказ3',	'01/05/18',	'Part1',	3)
,('Заказ4',	'01/01/17',	'Part2',	10)
,('Заказ5',	'01/01/19',	'Part2',	6)

DECLARE @Balance TABLE (PartName varchar(20), Balance int ) 
INSERT INTO @Balance  VALUES 
('Part1',	20)
,('Part2', 29)

DECLARE @Work TABLE (OrdNo varchar(20), WorkOrder varchar(20) )
INSERT INTO @Work VALUES 

('Заказ1',	'WO1')
,('Заказ1',	'WO2')
,('Заказ2',	'WO3')
,('Заказ2',	'WO4')
,('Заказ3',	'WO5')



SELECT 
  Z.* 
, W.WorkOrder

FROM(
  SELECT 
    O.OrdNo  
  , O.Date  
  , O.PartName 
  , O.OrdQty  
  , B.Balance
  , PartsReserved =  SUM(O.OrdQty) OVER (PARTITION BY O.PartName ORDER BY O.Date ROWS   unbounded preceding )
  , PartsRest = B.Balance - (SUM(O.OrdQty) OVER (PARTITION BY O.PartName ORDER BY O.Date ROWS   unbounded preceding ))
 
   FROM @Orders O 
     INNER JOIN  @Balance B ON B.PartName = O.PartName
   WHERE EXISTS (SELECT 1 FROM @Work W WHERE W.OrdNo = o.OrdNo) 
 ) Z
 INNER JOIN @Work W ON W.OrdNo = Z.OrdNo
 ORDER BY Z.Date, Z.OrdNo , W.WorkOrder

 
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564089
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О, спасибо.
Правда засаду с unbounded preceding всё равно надо как-то обойти.
А такой код отработает быстрее чем CTE? У меня с CTE очень тормозит.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564090
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще, и правда, так увлёкся CTE что протормозил насчёт обычного вложенного селекта.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564093
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetО, спасибо.
Правда засаду с unbounded preceding всё равно надо как-то обойти.
А такой код отработает быстрее чем CTE? У меня с CTE очень тормозит.
Что вы к этому CTE придрались... Это просто более удобная форма записи запроса.

Код: sql
1.
2.
3.
4.
5.
6.
7.
SELECT * FROM (SELECT * FROM (SELECT * FROM TableA) as rez) as rez2
--тоже самое что
;WITH Rez AS
  (SELECT * FROM TableA),
Rez2 AS
  (SELECT * FROM Rez)
SELECT * FROM Rez2


SQL сервер разворачивает ваше CTE в одно большое выражение...
И если вам кажется что
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
;WITH CTE AS
  (SELECT * FROM TableA),
CTE2 AS
  (SELECT * FROM CTE WHERE ID < 5).
CTE3 AS
  (SELECT * FROM CTE WHERE ID > 10)
SELECT * FROM CTE2 AS c2
JOIN CTE3 AS c3
  ON c3.ID = c2.ID


Сервер 1 раз выполнит SELECT * FROM TableA то вы заблуждаетесь....
Потому что он развернет это в
Код: sql
1.
2.
3.
SELECT * FROM (SELECT * FROM (SELECT * FROM TableA) WHERE ID < 5) AS c2
JOIN (SELECT * FROM (SELECT * FROM TableA) WHERE ID > 10) AS c3
  ON c3.ID = c2.ID


Как видите читаем TableA 2 раза...


P.S. Код с оконными функциями отработает быстрее чем вложенные корреляционные запросы, которым кстати тоже нарастающие итоги считаются...
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564094
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
https://blogs.technet.microsoft.com/isv_team/2011/07/26/1080/

Вот вам 4 примера расчета нарастающих итогов... Выбирайте какой хотите..
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564098
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite,

Спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564160
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite https://blogs.technet.microsoft.com/isv_team/2011/07/26/1080/
Вот вам 4 примера расчета нарастающих итогов... Выбирайте какой хотите..
Лучший из 4х примеров автор не может, у него лапки 2008й. 2 других - корявое тормозное бе.
Так, что выбор только один - сэлф джойн.


Кстати, это очень показательный топик. В очередной раз человек вместо того, чтоб задать вопрос по сути задачи, задает вопрос по сути того, что он принял за её решение.

Ведь "Как использовать ОТВ в ОТВ" и "Как посчитать набегающий итог без окон" - принципиально разные задачи.

Пожалуй, добавлю этот топик в закладку, как эталонный.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564238
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

Вообще-то всё ровно наоборот.
Изначальный была описана суть задачи и задан вопрос каков best practice.

Здесь (кроме десятков неконструктивных наездов) советовали варианты с CTE.
И я так до сих пор и не понял в чём преимущество предложенного Вами решения перед CTE.
А учитывая 2008 APPLY вроде как оптимальное решение.

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

Поэтому задаёт вопрос общий - как лучше сделать. Каков консепт?
А ему в ответ - чего синтаксис не гуглил??!!! Начинается длинная разборка насчёт синтаксиса. А через три простыни выясняется что решение совсем не там. Тогда наезд - а зачем про этот синтаксис спрашивал???!!!

В любом случае, мне лично из этой переписки один сплошной профит, получил хороший мастер-класс по T-SQL.
За что всем пинавшим-помогавшим огромное спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564262
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnetВообще, это очень показательный топик, хорошо демонстрирует непонятки между новичком и экспертом.
...
Поэтому задаёт вопрос общий - как лучше сделать. Каков консепт?
Именно, грамотный новичок и задает вопрос - как лучше сделать.

А у вас получилось: "Я тут два гвоздодера нашел, как мне их соединить? Может сваркой? Или еще как?" И только через пару страниц выясняется, что надо шуруп закрутить, и лучше всего воспользоваться шуруповертом (или, учитывая ограниченность ваших инструментов из-за версии сервера - отверткой).
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564268
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что значит чем лучше мой вариант чем ЦТЕ.

Вопрос в том, для решения какой задачи лучше?

Для набегающего итога?
Окно >> Сэлфджоин >> ОТВ >> Курсор
Поскольку твой 2008 не может решить задачу окном, то тебе нужен самоджойн.
Почему лучше, потому, что быстрее. Просто быстрее во всех случаях.

Для инкапсуляции "промежуточных наборов данных"?
Это опять же бабушка на двое сказала. Лично я не люблю СТЕ из-за ограничений, которые они накладывают на написание кода. СТЕ ты обязан использовать СРАЗУ после объявления, и никак иначе. Понятно почему, потому, что это (кроме случая с рекурсией) простой синтаксический сахар, который развернется, в итоге в тоже что и
Код: sql
1.
SELECT  FROM (SELECT FROM) Z

.

Работу СТЕ ты не можешь, например, легко проверить во время написания процедуры, в отличие от #таблицы.

Ласт, бат нот лист, весь синтаксис ОТВ довольно необычен для скуль кода, и прямо скажем, режет глаз, особенно когда один за другим идет ворох ОТВшек- сложно распутывать.

Таким образом именно для меня ОТВ вообще ничем не лучше других способов вращать данные, при этом наличиствуют очевидные недостатки.


В моей картине мира есть ровно ДВА случая, когда нужно использовать именно ОТВ.

а) рекурсивные запросы
б) ты пишешь инлайн функцию, в которой у тебя физически нет возможности использовать временные таблицы для каких то предрасчетов.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564286
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileДля набегающего итога?
Окно >> Сэлфджоин >> ОТВ >> Курсор
Поскольку твой 2008 не может решить задачу окном, то тебе нужен самоджойн.
Почему лучше, потому, что быстрее. Просто быстрее во всех случаях.

как раз в 2008-ом нарастающий итог быстрее всего считается курсором
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564298
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Minamoto,

снова эти непохожие примеры про гвозди, шо ж их тут так любят?
я описал проблему и спросил как её решить.

новичок - он на то и новичок, что не знает что и где искать.
для вашего чсв важно считать меня неграмотным - наздоровье, я неграмотный.

кто хотел помочь - помог уже.
вон комментом ниже подробно объясняют, дают полезную информацию.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564304
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123 как раз в 2008-ом нарастающий итог быстрее всего считается курсором
Исследования в студию.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564306
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileВ моей картине мира есть ровно ДВА случая, когда нужно использовать именно ОТВ.

В моей наоборот... Я теперь только через CTE пишу.. удобнее же...
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
;WITH
SummaData AS
(
  SELECT
    t.Data,
    SUM(t.Amount) AS Amount
  FROM
    TableA AS t
  GROUP BY
    t.Data
),
CountData AS
(
  SELECT
    t.Data,
    COUNT(*) AS Cnt
  FROM
    TableB AS t
  GROUP BY
    t.Data
),
MergeData AS
(
  SELECT
    sd.Data,
    sd.Amount,
    cd.Cnt,
    ROW_NUMBER() OVER (PARTITION BY sd.Amount ORDER BY (SELECT NULL)) AS rown
  FROM
    SummaData AS sd
    JOIN CountData AS cd
      ON cd.Data = sd.Data
)
  SELECT
    md.Data,
    md.Amount,
    md.Cnt
  FROM
    MergeData AS md
  WHERE
    md.rown = 1


Напишите это без CTE
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
SELECT
  md.Data,
  md.Amount,
  md.Cnt
FROM
(
  SELECT
    sd.Data,
    sd.Amount,
    cd.Cnt,
    ROW_NUMBER() OVER (PARTITION BY sd.Amount ORDER BY (SELECT NULL)) AS rown
  FROM
  (
    SELECT
      t.Data,
      SUM(t.Amount) AS Amount
    FROM
      TableA AS t
    GROUP BY
      t.Data
  ) AS sd
    JOIN
    (
      SELECT
        t.Data,
        COUNT(*) AS Cnt
      FROM
        TableB AS t
      GROUP BY
        t.Data
    ) AS cd
      ON cd.Data = sd.Data
) AS md
WHERE
  md.rown = 1



Такие вещи очень хороши с OVER т.к. результат оконки нельзя использовать в WHERE в текущем контексте, поэтому если надо потом отфильтровать то надо оборачивать в подзапросы... А это удобнее с CTE

Важно только понимать что подзапросы не будут выполнятся в том порядке в котором они идут в CTE, а сервер после разворота сам решит...
Новички обычно на этом и спотыкаются.. Даже... Я не раз слышал от коллег работающих довольно долго с SQL но не хотящих вдаваться в подробности кухни MSSQL, что они когда так пишут всерьез думают что сервер и один раз выполнит и типа положит в буфер результат, чтобы N раз обратится.. и порядок выполнения тоже.... А потом удивляются откуда там 20 млрд reads и cpu умирает...
После чего мне хотелось сказать -50% к премии.. Жаль нет полномочий
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564307
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileЧто значит чем лучше мой вариант чем ЦТЕ.

Вопрос в том, для решения какой задачи лучше?

Для набегающего итога?
Окно >> Сэлфджоин >> ОТВ >> Курсор
Поскольку твой 2008 не может решить задачу окном, то тебе нужен самоджойн.
Почему лучше, потому, что быстрее. Просто быстрее во всех случаях.

Для инкапсуляции "промежуточных наборов данных"?
Это опять же бабушка на двое сказала. Лично я не люблю СТЕ из-за ограничений, которые они накладывают на написание кода. СТЕ ты обязан использовать СРАЗУ после объявления, и никак иначе. Понятно почему, потому, что это (кроме случая с рекурсией) простой синтаксический сахар, который развернется, в итоге в тоже что и
Код: sql
1.
SELECT  FROM (SELECT FROM) Z

.

Работу СТЕ ты не можешь, например, легко проверить во время написания процедуры, в отличие от #таблицы.

Ласт, бат нот лист, весь синтаксис ОТВ довольно необычен для скуль кода, и прямо скажем, режет глаз, особенно когда один за другим идет ворох ОТВшек- сложно распутывать.

Таким образом именно для меня ОТВ вообще ничем не лучше других способов вращать данные, при этом наличиствуют очевидные недостатки.


В моей картине мира есть ровно ДВА случая, когда нужно использовать именно ОТВ.

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

Очередной очень ценный коммент.
Если быстее - то не вопрос что лучше.

Насчёт как на глаз - мне интуитивно как раз CTE легче читается. Особенно когда тянет из разных баз.

И главное, так и не понял, как обойти unbounded preceding в 2008?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564310
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-CiteВажно только понимать что подзапросы не будут выполнятся в том порядке в котором они идут в CTE, а сервер после разворота сам решит...
Новички обычно на этом и спотыкаются.. Даже... Я не раз слышал от коллег работающих довольно долго с SQL но не хотящих вдаваться в подробности кухни MSSQL, что они когда так пишут всерьез думают что сервер и один раз выполнит и типа положит в буфер результат, чтобы N раз обратится.. и порядок выполнения тоже.... А потом удивляются откуда там 20 млрд reads и cpu умирает...

А откуда знаем как именно выполняется, чтоб избежать "20 млрд reads и cpu умирает".
Где почитать про это?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564313
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторВажно только понимать что подзапросы не будут выполнятся в том порядке в котором они идут в CTE, а сервер после разворота сам решит...
Ага, и в какой то момент твоя логика встанет колом, потому, что поменялось качество данных, слетела статистика, инопланетяне облучили твой сервак из космоса и так далее.

И человек, который подхватывает твою разработку, 10 раз проклянет тебя, за эти твои ОТВ.


авторНапишите это без CTE

SELECT .. INTO #SmallFilterTable
SELECT .. INTO #AggregateTable
SELECT .. INTO #IDs
...

SELECT ... FROM #IDs MERGE JOIN #SmallFilterTable LOOP JOIN #AggregateTable ... MaintTable OPTION(F ORCE ORDER )
;-)

Чего в твоих ЦТЕ попросту не взлетит.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564324
Фотография X-Cite
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileавторНапишите это без CTE

SELECT .. INTO #SmallFilterTable
SELECT .. INTO #AggregateTable
SELECT .. INTO #IDs
...

SELECT ... FROM #IDs MERGE JOIN #SmallFilterTable LOOP JOIN #AggregateTable ... MaintTable OPTION(F ORCE ORDER )
;-)

Чего в твоих ЦТЕ попросту не взлетит.

Так есть же голова... Смотрим.. Большой запрос с 20 подзапросами.. Данных в таблицах под 100 млн... Оптимизатор не может подобрать оптимальный толковый план..
Смотрим по частям и видим что можно часть данных перекинуть во времянки, положить туда индексов, и уже над ними проводить действия... И это будет быстрее...
Я же не говорю, что CTE везде и всегда... На все есть голова, знания, и опыт, чтобы понимать когда и что применять...
Но в большинстве случаев когда данных в среднем до 1 млн, оптимизатор отлично справляется... У нас есть View которая инкапсулирует в себе ценовые предложения для клиента с учетом скидок, наценок, правил и.т.п. View - Это одна большая инструкция, без времянок.. Подзапросов CTE там около 20 штук... Если их оформить одним запросом, то сам черт ногу сломит... А не View нельзя, потому что на нее маппится Entity Framework который считает ее метаобъектом и может над ней строить запросы используя свою объектную модель...

slovnetА откуда знаем как именно выполняется, чтоб избежать "20 млрд reads и cpu умирает".
Где почитать про это?

SET STATISTICS IO ON
SET STATISTICS TIME ON
Плюс планы запросов, плюс профайлер + понимание теории построения индексов и внутренних операторов MSSQL при построении плана, плюс понимание логического конвейера обработки запросов...
+ опыт.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564346
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileYasha123 как раз в 2008-ом нарастающий итог быстрее всего считается курсором
Исследования в студию.
репро приводит то, кто несет фигню.
но специально для вас вот, пожалуйста:
Best approaches for running totals – updated for SQL Server 2012
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564355
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123Cammomileпропущено...

Исследования в студию.
репро приводит то, кто несет фигню.
но специально для вас вот, пожалуйста:
Best approaches for running totals – updated for SQL Server 2012 Вы грамотно не выделили последнее предложение
Все же не самым быстрым, а с минимальным количеством чтений. По крайней мере, в этом репро у курсора четвертое место по скорости.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564363
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MinamotoYasha123пропущено...

репро приводит то, кто несет фигню.
но специально для вас вот, пожалуйста:
Best approaches for running totals – updated for SQL Server 2012 Вы грамотно не выделили последнее предложение
Все же не самым быстрым, а с минимальным количеством чтений. По крайней мере, в этом репро у курсора четвертое место по скорости.
товарищ, вы о чем?
мы говорим о 2008 -ом?
значит, window functions-решения мы отметаем, так?
ААрон отмел CTE и quirky update, и даже написано почему.

ну и наконец, Камомиля утветждал, что "самоджойн быстрее всего".
ну так вот вам картинкой время выполнения курсора и "самоджойна".
вы правда не видите, что быстрее?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564367
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
для тех, кто не видит, что речь о 2008
+ cursor vs Сэлфджоин
Yasha123CammomileДля набегающего итога?
Окно >> Сэлфджоин >> ОТВ >> Курсор
Поскольку твой 2008 не может решить задачу окном, то тебе нужен самоджойн .
Почему лучше, потому, что быстрее. Просто быстрее во всех случаях .

как раз в 2008-ом нарастающий итог быстрее всего считается курсором
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564388
Alexander Us
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторНапишите это без CTE
SELECT .. INTO #SmallFilterTable
SELECT .. INTO #AggregateTable
SELECT .. INTO #IDs
...


Да, (если возможно) лучше без сложных CTE.
Времменые таблицы - оч. полезная вещь.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564390
Minamoto
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123Minamotoпропущено...
Вы грамотно не выделили последнее предложение
Все же не самым быстрым, а с минимальным количеством чтений. По крайней мере, в этом репро у курсора четвертое место по скорости.
товарищ, вы о чем?
мы говорим о 2008 -ом?
значит, window functions-решения мы отметаем, так?
ААрон отмел CTE и quirky update, и даже написано почему.

ну и наконец, Камомиля утветждал, что "самоджойн быстрее всего".
ну так вот вам картинкой время выполнения курсора и "самоджойна".
вы правда не видите, что быстрее?
О том, что он является самым быстрым при исключении ненадежных способов, которые, теоретически, могут дать неверные результаты (но это не точно). Но не "самым быстрым", о чем заявляли вы.
Если бы вы сразу сказали, что "курсор быстрее самоджойна", и привели бы точно такое же обоснование - вопросов бы не было )
Я лишь зацепился за фразу "It has the highest duration of the "faster" solutions".
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564394
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X-Cite А не View нельзя, потому что на нее маппится Entity Framework который считает ее метаобъектом и может над ней строить запросы используя свою объектную модель...

Типичная ситуация, когда херовое проектирование тянет за собой плохой код. Это аргумент не в защиту СТЕ, это аргумент против того рукожопа, который 20 СТЕ свел в одно представление.



Yasha123 , окей, картинка убедительная. Я в 2008 не работал уже лет 6.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564396
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правда, остается вопрос, почему по защите аргумента "в 2008 курсой быстрее" ты приводишь статью про "2012", но это мы оставим на твоей совести.

Протестировать сам я не могу, за неимением 2008р2 под рукой, а в сети, увы, не смог найти подобного исследования.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564405
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
slovnet
И главное, так и не понял, как обойти unbounded preceding в 2008?

Ну вот видишь, по последним данным от Ящьки123, самое быстрое в твоем случае, это курсор. Если, конечно, у тебя не стоит задача написать функцию. Тогда курсор не подойдет.

под спойлером самоджойн если ты не разобрался
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
DECLARE 
  @Orders TABLE (
  ID int identity (1,1) 
, OrdNo varchar(20) 
, Date datetime
, PartName varchar(20) 
, OrdQty int) 

INSERT INTO @Orders VALUES 
 ('Заказ1',	'01/02/18',	'Part1',	5)
,('Заказ2',	'01/01/18',	'Part1',	8)
,('Заказ3',	'01/05/18',	'Part1',	3)
,('Заказ4',	'01/01/17',	'Part2',	10)
,('Заказ5',	'01/01/19',	'Part2',	6)


SELECT
O.OrdNo
, O.OrdQty 
, RunningTotal = SUM(ISNULL(O2.OrdQty, 0)) 

, O.Date
, O.Id


FROM @Orders O 
LEFT JOIN @Orders O2 ON O2.ID <= O.ID
GROUP BY O.OrdNo
, O.OrdQty 
, O.Date
, O.Id
ORDER BY O.ID 

...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564406
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

slovnetИ главное, так и не понял, как обойти unbounded preceding в 2008?

Так можно в 2008 сделать самоджойном или нет?
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564407
slovnet
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cammomile,

Спасибо.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564428
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MinamotoО том, что он является самым быстрым при исключении ненадежных способов, которые, теоретически, могут дать неверные результаты (но это не точно). Но не "самым быстрым", о чем заявляли вы.
Если бы вы сразу сказали, что "курсор быстрее самоджойна" , и привели бы точно такое же обоснование - вопросов бы не было )
Я лишь зацепился за фразу "It has the highest duration of the "faster" solutions".
у меня вообще-то приведена цитата того,
что я опровергаю.
и на картинке у меня подчеркнуто именно то, что относится к запрашиваемому репро.

товарищ попросил "исследования в студию"
в ответ на мою реплику о курсоре, который в 2008-ом быстрее.

а почему я ему не рассказываю о "ненадежных способов, которые, теоретически, могут дать неверные результаты (но это не точно)",
это мое личное дело
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564431
Фотография Yasha123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
CammomileНу вот видишь, по последним данным от Ящьки123
исследование не мое, а Аарона.
а имя не корежь, оно не мое, так звали моего покойного кота.
но если тебе доставляет удовольствие,
то да, наверняка он в гробу перевернулся от такого к нему внимания
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564433
Cammomile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Yasha123... а имя не корежь...
но при этом
Yasha123... ну и наконец, Камомиля утветждал...


За собой следи, для начала.
...
Рейтинг: 0 / 0
Best practice по сведению двух CTE
    #39564521
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторо курсоре, который в 2008-ом быстрее

Собственно, я в этом и не сомневался, т.к. данные формируются за один проход в отличие от других способов.
...
Рейтинг: 0 / 0
98 сообщений из 98, показаны все 4 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Best practice по сведению двух CTE
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]