powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Запрос много ко многим
26 сообщений из 26, показаны все 2 страниц
Запрос много ко многим
    #39660673
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть таблица плана : Номенклатуру,дата,количество. Номенклатура может стоять в плане на несколько дат.
Номенклатура состоит из комплектующих(получаю рекурсивным запросом).
Нужно получить сколько комплектующих требуется на каждую дату.
Я циклом прохожу весь план и записываю комплектующие с датой во временную таблицу. Потом группирую по комплектующим и дате.
Как лучше решить эту задачу?
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660680
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВаселинаКак лучше решить эту задачу?Рекурсивным CTE можно получить всё одним запросом.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660693
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alexeyvg, Где же здесь рекурсия? Рекурсивным сте я получаю список комплектующих на каждую номенклатура.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660701
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Васелина,

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
With cte as
(Select Деталь, КолВо From План Where Дата Between @ДатаНач and @ДатаКон
Union all
Select b.Деталь, b.КолВо * a.КолВо --Количество сборок в плане * на количество деталей в сборке
 From cte a
 join Сборки b on a.Деталь = b.Сборка
)
Select Деталь,Sum(КолВо) as ОбщееКоличество 
 From CTE a
Where not exists (Select 1 From Сборки b Where a.Деталь = b.Сборка)
Group by Деталь
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660702
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если по датам:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
With cte as
(Select Деталь, Дата, КолВо From План Where Дата Between @ДатаНач and @ДатаКон
Union all
Select b.Деталь, a.Дата, b.КолВо * a.КолВо --Количество сборок в плане * на количество деталей в сборке
 From cte a
 join Сборки b on a.Деталь = b.Сборка
)
Select Деталь,Дата,Sum(КолВо) as ОбщееКоличество 
 From CTE a
Where not exists (Select 1 From Сборки b Where a.Деталь = b.Сборка)
Group by Деталь,Дата
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660724
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Васелинаalexeyvg, Где же здесь рекурсия? Рекурсивным сте я получаю список комплектующих на каждую номенклатура.А, извиняюсь. невнимательно прочитал.

Так осталось самое простое - добавить в запрос в нужных местах SUM, COUNT и GROUP BY
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660738
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kopelly,
With cte as
(Select сборка, Дата, КолВо From План Where Дата Between @ДатаНач and @ДатаКон
Union all
Select b.Деталь, a.Дата, b.КолВо * a.КолВо --Количество сборок в плане * на количество деталей в сборке
From cte a
join Сборки b on a.Деталь = b.сборка)
Select Деталь,Дата,Sum(КолВо) as ОбщееКоличество
From CTE a
Where not exists (Select 1 From Сборки b Where a.Деталь = b.Сборка)
Group by Деталь,Дата

В плане стоят стоят сборки, а не детали.
Запрос зациклился.Рекурсия превышает 100.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39660755
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Васелина, Если бы не было поля дата , то можно поставить SUm , group. b и связать две таблицы по изделию.
Но в таблице План Изделие повторяется несколько раз и в таблице с комплектующими изделие повторяется на каждую комплектующую. Количество комплектующих суммируется неправильно.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661020
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Васелина,
Давай пример данных - советы будут предметнее.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661035
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kopelly,
Задача стоит такая. Есть план на месяц. Который состоит из ежедневных планов. Номенклатура может повторяться .
Пример таблицы

изделие1 01-06-2018 5
изделие1 02-06-2018 3
изделие1 03-06-2018 1
изделие2 04-06-2018 4
изделие1 04-06-2018 5

Есть таблица иерархическая комплектующих и материалов изделий

Мне нужно на каждый день вытащить расход краски.

Я циклом обхожу таблицу план
вытаскиваю рекурсивным сте комплектующие по каждому изделию и выбираю краску и записываю данные во временную таблицу. Потом с ней работую. Можно ли эту задачу решить без цикла.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661038
Посетитель
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВаселинаМожно ли эту задачу решить без цикла.
можно.

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

более предметный ответ как уже неоднократно сказали, требует полного набора тестовых данных.
и код Ваш покажите, если не жалко :)
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661056
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВаселинаKopelly,
Задача стоит такая. Есть план на месяц. Который состоит из ежедневных планов. Номенклатура может повторяться .
По идее 21490650 решает такую задачу.
Либо расписывай структуру всех таблиц (с наименованием и назначением полей), либо ищи ошибку в переносе логики под свои данные, либо просто выложи текст запроса который приводит к зацикливанию.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661177
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kopelly,
with T(spvx,kodizd,kodsb,kodvx, kol,lv) AS
(SELECT spvx,s.kodizd,s.kodizd as kodsb,kodvx, kol,
1 AS lv
FROM sostav s ,(select kodizd from plano where dataz between '01-06-2018' and '30-06-2018' group by kodizd) as p
WHERE s.kodizd=p.kodizd
UNION ALL
SELECT s.spvx, s.kodizd,t.kodvx as kodsb,s.kodvx, s.kol*t.kol,
t.lv + 1 AS lv
FROM (sostav s inner join t on ( s.kodizd = t.kodvx ))
)
SELECT kodvx as Код, i1.izd as vxod,i2.izd ,lv ,kol
FROM ( T inner join izd i1 on (i1.Код=t.kodvx ) inner join izd i2 on i2.Код=t.kodsb )
where i1.izd='Краска'
order by lv
Сдесь группировка только по изделиям. Он не зацикливается . Но результат выдает неправильно. Увеличивает с строки изделие , комплектующие количество пропорционально количеству строк комплектующих в составе изделия.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661179
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если я еще и дату добавлю в группировку то еще увеличивается пропорционально количеству строк по номенклатуре в плане.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39661225
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Васелина,
Если так?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
with T(dataz,spvx,kodizd,kodsb,kodvx, kol,lv) AS 
(SELECT p.dataz,spvx,s.kodizd,s.kodizd as kodsb,kodvx, sum(p.kol*s.kol), 
 1 AS lv 
 FROM plano p 
 join sostav s on s.kodizd=p.kodizd
 where p.dataz between '01-06-2018' and '30-06-2018'
 Group by dataz,spvx,s.kodizd, kodvx
	UNION ALL 
 SELECT t.dataz,s.spvx, s.kodizd,t.kodvx as kodsb,s.kodvx, s.kol*t.kol, 
	t.lv + 1 AS lv 
 FROM sostav s 
 inner join t on  s.kodizd = t.kodvx
) 
SELECT t.dataz,t.kodvx as Код, i1.izd as vxod,i2.izd ,sum(t.kol)
FROM T 
inner join izd i1 on i1.Код=t.kodvx 
inner join izd i2 on i2.Код=t.kodsb
where i1.izd='Краска'
Group by t.dataz,t.kodvx,i1.izd,i2.izd 



Увеличивает с строки изделие , комплектующие количество пропорционально количеству строк комплектующих в составе изделия.
Логично если в каждом комплектующем изделия есть "Краска" - группирок то нет.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662051
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kopelly,
Запрос работает неправильно ,Краска может входить в разные сборки , при этом сами сборки могут входить в разные сборки.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662071
Фотография НиколайСН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то я не понял каким образом Номенклатура и Краска зависят друг от друга?

А чем обычная группировка не помогает?
Зачем вообще ТУТ Рекурсия и сборка данных на Номенклатуру?
Где Тут отношение М:М, если ты указал ТОЛЬКО одну таблицу?
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662233
982183
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НиколайСН,

Видимо там многопередельное производство. (что подтверждается последним постом)
С достаточно стандартной схемой данных комплектов.
И автор не удосужилась всё это описать, уповая на телепатические способности коллег.
и обыденность ситуации.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662256
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
982183, Вы правы. Хотелось бы узнать . Как правильнее реализовать механизм разузлования номенклатуры.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662263
982183
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Последовательным разукомплектованием.
Другого способа нет.

если бы вы привели тестовый пример комплектов
(например здесь - http://sqlfiddle.com/ )
и в кратко описали структуру данных,
то можно было бы говорить более предметно.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662277
982183
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тем более, что возможна ошибка в описании комплектов, при которой возникает зацикливание.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662360
Фотография НиколайСН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВаселинаKopelly,
Задача стоит такая. Есть план на месяц. Который состоит из ежедневных планов. Номенклатура может повторяться .
Пример таблицы

изделие1 01-06-2018 5
изделие1 02-06-2018 3
изделие1 03-06-2018 1
изделие2 04-06-2018 4
изделие1 04-06-2018 5

Есть таблица иерархическая комплектующих и материалов изделий

Мне нужно на каждый день вытащить расход краски.

Я циклом обхожу таблицу план
вытаскиваю рекурсивным сте комплектующие по каждому изделию и выбираю краску и записываю данные во временную таблицу. Потом с ней работую. Можно ли эту задачу решить без цикла.

Я так понял что имеется всё-таки 2 таблицы, где одна из них имеет тип фактовой (значения по расходу краски) и Нормативно справочную (таблица иерархическая комплектующих и материалов изделий).

Тем более тогда не понимаю зачем тебе рекурсия, тем более это делается скорее всего одним запросом по связке [KEY] и [PARENT_KEY], ибо я увидел только 2 уровня НСИ: Изделие и Комплектующие.

Если тебе надо посчитать количества комплектующих (краски) за определенную дату, то это делается SUM() с банальным Джоином 2-х этих таблиц и группировкой (GROUP BY) по дате.

Или же я не понимаю?

В идеале конечно же хотелось бы более правильно поставленную задачу, не уповая на телепатию архитектуры Вашей БД, где описано: ДАНО и ВОПРОС
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662364
982183
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
НиколайСН,

У неё многопередельное производство.
Пельмени=тесто+фарш
Тесто=мука+яйца
Фарш=мясо+сало+соя
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662413
Васелина
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как найти краску я знаю. Нахожу все изделия рекурсивным запросом в которые входит краска и стыкую с планом изделий на месяц по датам, получается запрос один ко многим. А как разузловать всю номенклатуру по всем комплекутющим и материалам без цикла я не знаю.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662415
Фотография НиколайСН
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
982183,

Ну если так, то ДА, рекурсией собирается элементарно - выше примеры.

Ну а дальше кто мешает выполнить GROUP BY и сделать SUM обычным запросом?
типа:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT 
    SUM(Значение), 
    Краска, 
    Дата 
WHERE Деталь = 'Краска' 
GROUP BY 
    Краска, 
    Дата 


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

Да собстна, уже есть примеры выше, осталось мизер допилить и готово.
...
Рейтинг: 0 / 0
Запрос много ко многим
    #39662468
Kopelly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пример подогнан под 10 единиц краски в каждом изделии:

Код: 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.
54.
55.
56.
Create table plano  ( kodizd int,dataz date, Kol int);
insert into plano values (1,'20180601',5);
insert into plano values (1,'20180602',3);
insert into plano values (1,'20180603',1);
insert into plano values (2,'20180604',4);
insert into plano values (1,'20180604',5);

Create table sostav (spvx int, kodizd int, kodvx int, Kol int);
insert into sostav values (0,1,10,2);
insert into sostav values (0,1,20,1);
insert into sostav values (0,1,200,5);
insert into sostav values (0,10,200,2);
insert into sostav values (0,10,300,1);
insert into sostav values (0,20,200,1);
insert into sostav values (0,20,400,1);
insert into sostav values (0,2,10,5);

Create table izd ( Код int, izd nvarchar(20));
insert into izd values (1,N'Изделие-1');
insert into izd values (10,N'Деталь-1');
insert into izd values (20,N'Деталь-2');
insert into izd values (200,N'Краска');
insert into izd values (300,N'Болванка-1');
insert into izd values (400,N'Болванка-2');
insert into izd values (2,N'Изделие-2');

with T(dataz, spvx, kodizd, kodsb, kodvx, kol_izd, kol_sb, kol,lv) AS 
(SELECT dataz,spvx,s.kodizd,s.kodizd as kodsb,kodvx, sum(p.kol), sum(p.kol*s.kol),sum(p.kol*s.kol), 
 1 AS lv 
 FROM plano p 
 join sostav s on s.kodizd=p.kodizd
 where p.dataz between '20180601' and '20180630'
 Group by dataz,spvx,s.kodizd, kodvx
	UNION ALL 
 SELECT dataz,s.spvx, t.kodizd,s.kodizd as kodsb,s.kodvx, t.kol_izd, t.kol, s.kol*t.kol, 
	t.lv + 1 AS lv 
 FROM sostav s 
 inner join t on  s.kodizd = t.kodvx
) 
SELECT dataz,t.kodvx as Код, 
i3.izd ,
t.kol_izd,
i1.izd as vxod,
sum(t.kol) as Kol
/*
--Расшифровка по изделиям/сборкам/комплектющим
i1.izd as vxod,t.kol, --комплектющие
i2.izd as sborka,t.kol_sb, --сборки
i3.izd as Izdelie, t.kol_izd, --изделия из плана
t.lv */
FROM T 
inner join izd i1 on i1.Код=t.kodvx 
inner join izd i2 on i2.Код=t.kodsb
inner join izd i3 on i3.Код=t.kodizd
where i1.izd=N'Краска'
Group by dataz,t.kodvx, i1.izd,i3.izd,t.kol_izd



На мой взгляд результат верный:
datazКодizdkol_izdvxodKol2018-06-01200Изделие-15Краска50 2018-06-02200Изделие-13Краска30 2018-06-03200Изделие-11Краска10 2018-06-04200Изделие-15Краска50 2018-06-04200Изделие-24Краска40
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Запрос много ко многим
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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