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

Откуда: Калуга
Сообщений: 145
Здравствуйте! Помогите, пожалуйста, составить запрос... или может быть направьте в нужное русло...
Итак. Есть таблица с полями Id, ParentId, Price, где Id - уник идентификатор, ParentId - идентификатор родительской группы, Summ - сумма группы (сколько денег в этой группе).
Мне нужно составить запрос таким образом, чтобы по конкретному ParentId выводились Id и суммы по Price, !НО! сумма не только по Id, которые принадлежат данному ParentId, но и всем Id рекурсивно вложенным. Уровень вложенности - бесконечный. Спасибо заранее!
7 окт 11, 08:47    [11399339]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleksey_sql, читать рекурсивный CTE, если версия сервера позволяет. Либо с помощью циклов, для версии сервера <2005.
7 окт 11, 08:55    [11399354]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
kDnZP,

ммм... у меня слабовато с этим... может быть подскажешь пример запроса?
7 окт 11, 09:07    [11399380]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleksey_sql, на форуме и в BOL примеров море. Мне искать лень, а вам?
7 окт 11, 09:29    [11399470]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
kDnZP,

Как написать рекурсивный запрос, который выводит всех потомков я разобрался:
WITH T (Id, ParentId, nLevel) AS
( SELECT Id, IdParent, 0 nLevel FROM Planning (NOLOCK) WHERE id=4
UNION ALL
SELECT t1.Id, t1.IdParent, 1 + nLevel
FROM Planning T1 (NOLOCK) JOIN T ON T1.IdParent=T.Id
) SELECT * FROM T


Но мне нужно по конкретному ParentId выводить только один уровень и поле, содержащее сумму всех внутренних уровней. Это для меня сложновато, потому и прошу помощи...
7 окт 11, 09:34    [11399494]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql,

потом делаете группировку по ParentID и выводите что хотите.
7 окт 11, 09:36    [11399506]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iljy,

По ParentId группировку делать не получится, т.к. ParentId одинаковый только у уровня, который я вывожу, а у уровня глубже, он уже другой.
7 окт 11, 09:38    [11399511]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql
iljy,

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

А кто вам мешает при выполнении рекурсивного запроса тащить в нижние уровни значение ParentID с самого верхнего уровня? Добавьте еще одно поле, делов-то.
7 окт 11, 09:43    [11399554]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iljy, хм... гламурно) щас буду пробовать. спасибо! о результате отпишусь!
7 окт 11, 09:46    [11399583]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iljy, ничего не получается :(
не получается parentid сохранять нужный. вот что делаю:

WITH T (Id, IdParent, IdParentMain, nLevel, IdNomenclature, TypeP, Count_1, Price_1, Comment_1) AS
( SELECT Id, IdParent, IdParent, 0 nLevel, IdNomenclature, TypeP, Count_1, Price_1, Comment_1 FROM Planning (NOLOCK) WHERE IdParent=0
UNION ALL
SELECT t1.Id, T1.IdParent, T.IdParent, 1 + nLevel, t1.IdNomenclature, t1.TypeP, t1.Count_1, t1.Price_1, t1.Comment_1
FROM Planning T1 (NOLOCK) JOIN T ON T1.IdParent=T.Id
)
SELECT * FROM T
INNER JOIN Dictionary_Nomenclature D ON (T.IdNomenclature = D.Id)
7 окт 11, 11:22    [11400408]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql,

конечно не получается, у вас дырка в логике. Как определяются корневые элементы? И как по ним идентифицировать поддерево?
7 окт 11, 11:28    [11400470]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
HandKot
Member

Откуда: Sergiev Posad
Сообщений: 3058
SELECT t1.Id, T1.IdParent, T.Id, 1 + nLevel, t1.IdNomenclature, t1.TypeP, t1.Count_1, t1.Price_1, t1.Comment_1
?
7 окт 11, 11:28    [11400474]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iljy, самые корневые элементы имеют pid = 0, а далее - класическое дерево...

1 0 10.1
2 0 34.6
3 1 45.4
4 1 44.1
5 1 47.6
6 2 22.3
7 3 79.1
8 4 121.2
9 7 456.3

типа такого.
7 окт 11, 11:40    [11400612]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iap
Member

Откуда: Москва
Сообщений: 47142
aleksey_sql
iljy, самые корневые элементы имеют pid = 0, а далее - класическое дерево...

1 0 10.1
2 0 34.6
3 1 45.4
4 1 44.1
5 1 47.6
6 2 22.3
7 3 79.1
8 4 121.2
9 7 456.3

типа такого.
HandKot Вам же ответил.
Передавайте в одном из полей в каждой строке одно и то же значение T.Id корневого SELECTа.
7 окт 11, 11:45    [11400679]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iap, нет. не получается. мне нужно считать суммы всех вложенных подгрупп. а так - я никак не сгруппирую данные.
7 окт 11, 11:49    [11400752]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iap,

получается, как вы говорите - T.id равен T1.IdParent... тогда и смысла в нем нету...
7 окт 11, 11:54    [11400815]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql,

так у вас этот самый T.ID содержит идентификатор самого корневого элемента, разьве не это нужно?
7 окт 11, 12:04    [11400924]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iljy,

я написал запрос, который по IdParent дергает все-все узлы дерева, которые принадлежат элементам с IdParent = значение
вот собственно запрос:
WITH T (Id, IdParent, IdParentMain, nLevel, IdNomenclature, TypeP, Count_1, Price_1, Comment_1) AS
( SELECT Id, IdParent, IdParent, 0 nLevel, IdNomenclature, TypeP, Count_1, Price_1, Comment_1 FROM Planning (NOLOCK) WHERE IdParent=0
UNION ALL
SELECT t1.Id, T1.IdParent, T.IdParent, 1 + nLevel, t1.IdNomenclature, t1.TypeP, t1.Count_1, t1.Price_1, t1.Comment_1
FROM Planning T1 (NOLOCK) JOIN T ON T1.IdParent=T.Id
)
SELECT * FROM T
INNER JOIN Dictionary_Nomenclature D ON (T.IdNomenclature = D.Id)

теперь мне хочется, чтобы этот запрос возвращал только элементы дерева с IdParent = значение, !но! чтобы в поле допустим, Price_1 была сумма полей Price_1 элементов, которые ответвляются от своих "родителей".
7 окт 11, 12:09    [11400978]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
kDnZP
Member [заблокирован]

Откуда: ★[msg=16399436]★[msg=20850760]
Сообщений: 11289
aleksey_sql, скрипт создания таблицы + тестовые данные + ожидаемый результат = существенно ускорят написание скрипта для вас.
7 окт 11, 12:19    [11401087]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
kDnZP,

CREATE TABLE [dbo].[table1] (
[Id] int IDENTITY(1, 1) NOT NULL,
[ParentId] int NULL,
[Name] text COLLATE Cyrillic_General_CI_AS NULL,
[Price] decimal(2, 0) NULL,
CONSTRAINT [PK__table1__3214EC0707020F21] PRIMARY KEY CLUSTERED ([Id])
)
ON [PRIMARY]
TEXTIMAGE_ON [PRIMARY]
GO


INSERT INTO [dbo].[table1] ([Id], [ParentId], [Name], [Price])
VALUES (1, 0, N'Один', 8)
GO

INSERT INTO [dbo].[table1] ([Id], [ParentId], [Name], [Price])
VALUES (2, 0, N'Два', 12)
GO

INSERT INTO [dbo].[table1] ([Id], [ParentId], [Name], [Price])
VALUES (3, 1, N'Один-ветка', 11)
GO

INSERT INTO [dbo].[table1] ([Id], [ParentId], [Name], [Price])
VALUES (4, 3, N'Один-ветка-ветка', 3)
GO

INSERT INTO [dbo].[table1] ([Id], [ParentId], [Name], [Price])
VALUES (5, 2, N'Два-ветка', 4)
GO

Хочется, чтобы при запросе по IdParent = 0 выдавался такой результат:
1 0 Один 22 (это 8+11+3)
2 0 Два 16 (12+4)

ну и соответственно, чтобы при запросе по IdParent = 1 выдавался такой результат:
3 1 Один-ветка 14 (11+3)

и т.д. в таком духе...
7 окт 11, 12:34    [11401248]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql,

ну и где проблема-то?
CREATE TABLE #table1 (
 [Id] int NOT NULL,
 [ParentId] int NULL,
 [Name] nvarchar(max) COLLATE Cyrillic_General_CI_AS NULL,
 [Price] decimal(2, 0) NULL,
 CONSTRAINT [PK__table1__3214EC0707020F21] PRIMARY KEY CLUSTERED ([Id])
)

INSERT INTO #table1 ([Id], [ParentId], [Name], [Price])
VALUES (1, 0, N'Один', 8),(2, 0, N'Два', 12),(3, 1, N'Один-ветка', 11),(4, 3, N'Один-ветка-ветка', 3),(5, 2, N'Два-ветка', 4)

declare @IdParent int = 1 -- 0, 2, 184, все, что вам хочется

;WITH T AS
(
	SELECT Id, Id MainParent, 0 nLevel, Name, Price FROM #table1 WHERE ParentId=@IdParent
		UNION ALL
	SELECT t1.Id, MainParent, 1 + nLevel, t1.Name, t1.Price
	FROM #table1 t1 JOIN T ON T1.ParentId = T.Id 
) 
SELECT MainParent, MAX(case nLevel when 0 then Name else '' end) Name, SUM(Price) SUM_Price 
FROM T
GROUP BY MainParent

drop table #table1
7 окт 11, 12:48    [11401388]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
iljy,

теперь проблемы нет. спасибо огромное! буду читать буквари:)
7 окт 11, 13:03    [11401503]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
aleksey_sql
Member

Откуда: Калуга
Сообщений: 145
Помогите ещё разок, плиз! Как в этом запросе добавить поле, в которое выводить 1 или 0 в зависимости, есть у этой группы "дети" или нет. Заранее спасибо!
12 окт 11, 10:19    [11424712]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql,

MAX(SING(nLevel))
12 окт 11, 10:23    [11424735]     Ответить | Цитировать Сообщить модератору
 Re: Как быть с запросом  [new]
iljy
Member

Откуда:
Сообщений: 8711
aleksey_sql,

вернее лучше функции местами поменять, чуть быстрее будет.
12 окт 11, 10:25    [11424751]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить