powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Задача на накопительный итог
15 сообщений из 40, страница 2 из 2
Задача на накопительный итог
    #38421396
Гость333
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OblomПалеты заполняются только полностью. Итого 305 = 240 (PaletTypeId = 1) + 50(PaletTypeId = 2) + 10 (PaletTypeId = 3) + 5 (остаток).
Тема остатка не раскрыта.
В исходном посте для этой ячейки вы выделили 2 палеты по 10 единиц, т.е. одна палета была загружена только наполовину (на 5 единиц). А здесь у вас 5 — это остаток.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421398
Baal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно я тоже свою версию добавлю?
Код: 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.
IF OBJECT_ID('tempdb..#Cell') IS NOT NULL DROP TABLE #Cell;
IF OBJECT_ID('tempdb..#PaletType') IS NOT NULL DROP TABLE #PaletType;

CREATE TABLE #Cell(CellId int, Qty int);

INSERT INTO #Cell VALUES (1,305);
INSERT INTO #Cell VALUES (2,280);
INSERT INTO #Cell VALUES (3,250);
INSERT INTO #Cell VALUES (4,230);
INSERT INTO #Cell VALUES (5,210);

CREATE TABLE #PaletType(PaletTypeId int, Capacity int);

INSERT INTO #PaletType VALUES (1, 240);
INSERT INTO #PaletType VALUES (2, 50);
INSERT INTO #PaletType VALUES (3, 10);

GO

WITH cte(CellId,PaletTypeId,Capacity,Qty,PaletQuantity) AS (
	SELECT CellId,
           - 1 AS PaletTypeId,
           1000000 AS Capacity,
           Qty,
           0 AS PaletQuantity
    FROM #Cell
    UNION ALL
    SELECT CellId,
           PaletTypeId,
           Capacity,
           Qty,
           PaletQuantity
    FROM 
     (SELECT cte.CellId,
             p.PaletTypeId,
             p.Capacity,
             cte.Qty - (cte.Qty / p.Capacity) * p.Capacity AS Qty,
             cte.Qty / p.Capacity AS PaletQuantity,
             MAX(p.Capacity) OVER(PARTITION BY cte.CellId) AS max_cap
      FROM cte
      INNER JOIN #PaletType AS p
      ON (p.Capacity < cte.Capacity)) AS a
    WHERE a.Capacity = a.max_cap)
SELECT CellId,PaletTypeId,PaletQuantity
FROM cte
WHERE PaletQuantity > 0
ORDER BY CellId,PaletTypeId


Неполная палета остается в ячейке.
Выборка по размеру палеты, а не идентификатору.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421434
Oblom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Гость333OblomПалеты заполняются только полностью. Итого 305 = 240 (PaletTypeId = 1) + 50(PaletTypeId = 2) + 10 (PaletTypeId = 3) + 5 (остаток).
Тема остатка не раскрыта.
В исходном посте для этой ячейки вы выделили 2 палеты по 10 единиц, т.е. одна палета была загружена только наполовину (на 5 единиц). А здесь у вас 5 — это остаток.

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

Код: 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.
57.
58.
59.
60.
61.
62.
63.
64.
if object_id('tempdb..#numbers') is not null drop table #numbers
;with 
  L0(c) as (select 0 from (values (0),(0),(0)) x(c)) --3 Rows
 ,L1(c) as (select 0 from L0 a, L0 b, L0 c)          --27 Rows (3x3x3)
 ,L2(c) as (select 0 from L1 a, L1 b, L1 c)          --19683 Rows (27x27x27)
 ,L3(c) as (select 0 from L2 a, L2 b)                --387,420,489 Rows (19683x19683)
 ,NN(n) as (select row_number() over (order by (select 0)) from L3)
 
select Number=isnull(convert(int,n),0)
into #numbers  
from NN 
where n<=1000000

if object_id('tempdb..#ptn') is not null
drop table #ptn
 
select
c.CellId
,c.QTY
,pt.Capacity*(n.Number-1) node
,pt.PaletTypeId
,n.number-1 number
into #ptn
from	Cell	c	
		cross join 	PaletType pt
		inner join #numbers n
		on (n.Number-1)*pt.Capacity< c.Qty
		
if object_id('tempdb..#paths') is not null
drop table #paths		
select
n1.CellId
,sum(n1.number) n1
,sum(n2.number) n2
,sum(n3.number) n3
,sum(n4.number) n4
,SUM(n1.node+n2.node+n3.node+n4.node) totQuant
,SUM(n1.number+n2.number+n3.number+n4.number) cpal
into #paths
from #ptn n1
		inner join #ptn n2
		on	n2.cellid = n1.cellid
			and n2.paletTypeId = 2
		inner join #ptn n3
		on n3.cellid = n1.cellid
			and n3.paletTypeId = 3
		inner join #ptn n4
		on n4.cellid= n1.cellid
			and n4.paletTypeId = 4
where n1.PaletTypeId =1		
group by n1.cellId,n1.Qty,n1.number,n2.number,n3.number,n4.number
having SUM(n1.node+n2.node+n3.node+n4.node)>=	n1.QTY

;with opt as(
select
cellId
,min(n1+n2+n3+n4) optpath
from #paths
group by cellid)

select
p.*
from #paths p
where p.n1+p.n2+p.n3+p.n4 = (select optpath from opt o where o.cellid = p.CellId )
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421545
Фотография Shakill
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OblomИ да, мой косяк в формулировке: нужно реализовать "жадный" алгоритм, то есть минимальный остаток должен получиться минимальным числом палет. Проще говоря: сначала выбирается весь товар на самые вместительные палеты, потом на менее вместительные и так далее. Палеты заполняются только полностью. Итого 305 = 240 (PaletTypeId = 1) + 50(PaletTypeId = 2) + 10 (PaletTypeId = 3) + 5 (остаток).с учетом сказанного, поясните, как вы поступите в случае, если размер ячейки 250, а в наличии палеты размеров 240 и 50. возьмете одну палету 240 или пять по 50? если первое, то получится не минимальный остаток, если второе, то ваш алгоритм не подходит
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421623
Мистер Хенки
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ShakillOblomИ да, мой косяк в формулировке: нужно реализовать "жадный" алгоритм, то есть минимальный остаток должен получиться минимальным числом палет. Проще говоря: сначала выбирается весь товар на самые вместительные палеты, потом на менее вместительные и так далее. Палеты заполняются только полностью. Итого 305 = 240 (PaletTypeId = 1) + 50(PaletTypeId = 2) + 10 (PaletTypeId = 3) + 5 (остаток).с учетом сказанного, поясните, как вы поступите в случае, если размер ячейки 250, а в наличии палеты размеров 240 и 50. возьмете одну палету 240 или пять по 50? если первое, то получится не минимальный остаток, если второе, то ваш алгоритм не подходит
Кстати, если считать условие оптимизации как минимальный остаток и минимальное количество палет, то в моем способе последние два запроса меняются немного и все. Но на мой взгляд это крайне тяжелый способ с перебором всех возможных комбинаций палет + еще подразумевает применение динамики для произвольного количества палет
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
....
having SUM(n1.node+n2.node+n3.node+n4.node)<=	n1.QTY



select top 1 with ties
p.*
from #paths p
order by dense_rank() over (partition by cellid order by totQuant desc,cpal asc)
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421626
Мистер Хенки
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мистер Хенкиеще подразумевает применение динамики для произвольного количества палет


произвольного количества типоразмеров палет
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421730
ambarka_max
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача конечно прикольная, но чисто теоретическая, как в реальности это будет работать?
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421907
DimArie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!

Oblom (Мой коллега, я к нему подошел за консультацией) слегка изменил условие задачи.

По факту есть реальная задача:

Склад. Товар находится на паллетах в ячейках.

Структура хранения данных о товаре:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE TABLE Cell(CellId int, GoodsId int, Qty int)

INSERT INTO Cell VALUES (1, 1, 72)
INSERT INTO Cell VALUES (2, 1, 72)
INSERT INTO Cell VALUES (3, 1, 40)


INSERT INTO Cell VALUES (11, 2, 240)
INSERT INTO Cell VALUES (12, 2, 240)
INSERT INTO Cell VALUES (13, 2, 80)
INSERT INTO Cell VALUES (14, 2, 10)


INSERT INTO Cell VALUES (21, 3, 30)

INSERT INTO Cell VALUES (31, 4, 100)




Есть заказ на отгрузку, с детализацией вида:

Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE OrderDetail (OrderDetailId int, GoodsId int, Qty int)

INSERT INTO OrderDetail VALUES (101, 1, 120)
INSERT INTO OrderDetail VALUES (102, 2, 100)
INSERT INTO OrderDetail VALUES (103, 3, 70)
INSERT INTO OrderDetail VALUES (104, 4, 55)





Количество паллет с товаром конечно. Укладки товаров на паллетах различны, но как правило один товар укладывается 1-2 способами (вопросы оптимизации логистики).

Задача в том, чтобы подобрать из заказа максимальное количество товара паллетами. Если товара не хватает на паллетах, то он подбирается отдельно (то есть паллетно можно отдать меньше). Паллеты не дробятся -- складская техника за раз может взять одну паллету целиком.

При ситуации, описанной выше, когда нужно подобрать 250, а есть на складе паллеты по 240 и паллеты по 50, считаем оптимальным подобрать 240 (реализуем стратегию ускорения подбора в ущерб оптимизации хранения).


Хотелось бы на выходе получить таблицу вида:

Код: sql
1.
CREATE TABLE Result(OrderDetailId int, CellId int)



Код: plaintext
1.
2.
3.
4.
5.
6.
OrderDetailId CellId         
101           1                       
101           3              
102           13
102           14
103           21


Заранее спасибо и прошу прощения если что-то оформлено не так.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421925
ambarka_max
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А ничего, что может быть несколько заказов на отгрузку с пересекающимися данными для обхода?
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421935
DimArie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ambarka_maxА ничего, что может быть несколько заказов на отгрузку с пересекающимися данными для обхода?

Считаем, что заказы обрабатываются последовательно, и, после снятия паллеты, строка из таблицы Cell удаляется. То есть конкуренции за паллету нет.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421951
ambarka_max
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Алгоритмы это все хорошо, но уловите суть:
Если у вас на складе не один грузчик бегает, то просто жизненно необходимо (при расчете какую паллету из какой ячейки брать) учитывать эти данные и для других параллельных отгрузок. Своего рода в какой то момент времени должен происходить резерв по-палетно, а не по товару. И эта информация должна учитываться при расчете других отгрузок.
То есть, вот тот результат который вы хотите получить для отгрузки клиента №1 его нужно сохранить, и для расчета отгрузки клиента №2, результат резерва от первого - учитывать.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421964
DimArie
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ambarka_maxАлгоритмы это все хорошо, но уловите суть:
Если у вас на складе не один грузчик бегает, то просто жизненно необходимо (при расчете какую паллету из какой ячейки брать) учитывать эти данные и для других параллельных отгрузок. Своего рода в какой то момент времени должен происходить резерв по-палетно, а не по товару. И эта информация должна учитываться при расчете других отгрузок.
То есть, вот тот результат который вы хотите получить для отгрузки клиента №1 его нужно сохранить, и для расчета отгрузки клиента №2, результат резерва от первого - учитывать.

ambarka_max, вы полностью правы. На самом деле структура склада сложнее, резервирование происходит. Если быть точным, данный алгоритм как раз резервирует паллеты.

Но, по моему мнению, к самому алгоритму тонкости работы склада отношения не имеют. Как мне кажется, я описал достаточное количество полей для понимания задачи, и грузить дополнительными сложностями неспециалистов не хочу.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38421976
ambarka_max
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimArie... Если быть точным, данный алгоритм как раз резервирует паллеты.
Тогда я спокоен. Выдохнул.
...
Рейтинг: 0 / 0
Задача на накопительный итог
    #38423021
Baal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DimArie,

Если в заказе товар уникален, то так.
Код: 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.
IF OBJECT_ID('tempdb..#Cell') IS NOT NULL DROP TABLE #Cell;
IF OBJECT_ID('tempdb..#OrderDetail') IS NOT NULL DROP TABLE #OrderDetail;

CREATE TABLE #Cell(CellId int, GoodsId int, Qty int)

INSERT INTO #Cell VALUES (1, 1, 72)
INSERT INTO #Cell VALUES (2, 1, 72)
INSERT INTO #Cell VALUES (3, 1, 40)
INSERT INTO #Cell VALUES (11, 2, 240)
INSERT INTO #Cell VALUES (12, 2, 240)
INSERT INTO #Cell VALUES (13, 2, 80)
INSERT INTO #Cell VALUES (14, 2, 10)
INSERT INTO #Cell VALUES (21, 3, 30)
INSERT INTO #Cell VALUES (31, 4, 100)


CREATE TABLE #OrderDetail (OrderDetailId int, GoodsId int, Qty int)

INSERT INTO #OrderDetail VALUES (101, 1, 120)
INSERT INTO #OrderDetail VALUES (102, 2, 100)
INSERT INTO #OrderDetail VALUES (103, 3, 70)
INSERT INTO #OrderDetail VALUES (104, 4, 55)

GO

WITH cte(OrderDetailId,GoodsId,Qty,CellId,min_CellId,lvl,max_qty,cell_qty,used) AS (
	SELECT OrderDetailId,GoodsId,Qty,0 AS CellId,0 AS min_CellId,0 AS lvl,0 AS max_qty,0 AS cell_qty,
		  CAST(',' AS VARCHAR(MAX)) AS used
	FROM  #OrderDetail
	UNION ALL
	SELECT * FROM 
	(SELECT 
			OrderDetailId,
			cte.GoodsId,
			cte.Qty - cell.Qty AS Qty,
			cell.CellId,
			MIN(cell.CellId) OVER(PARTITION BY cte.GoodsID) AS min_CellId,
			cte.lvl + 1 AS lvl,
			MAX(cell.Qty) OVER(PARTITION BY cte.GoodsID) AS max_qty,
			cell.Qty AS cell_qty,
			cte.used + CAST(cell.CellId AS VARCHAR(MAX)) + ',' AS used
	 FROM cte
	 INNER JOIN #Cell AS cell
	 ON (cte.GoodsId = cell.GoodsId AND cte.Qty >= cell.Qty
		 AND cte.used NOT LIKE '%,' + CAST(cell.CellId AS VARCHAR(MAX)) + ',%')) AS a
	WHERE cell_qty = max_qty AND min_CellId = CellId)
SELECT OrderDetailId,CellId
FROM cte
WHERE CellId <> 0
ORDER BY cte.OrderDetailId,CellId
...
Рейтинг: 0 / 0
15 сообщений из 40, страница 2 из 2
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Задача на накопительный итог
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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