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

Откуда: Москва
Сообщений: 589
DECLARE @T TABLE ([order] INT,id int,category INT,people int)
INSERT INTO @T 
SELECT 1, 1, 1 ,56
UNION ALL 
SELECT 1, 2, 1, 57
UNION ALL 
SELECT 1, 3, 1, 45
UNION ALL 
SELECT 2, 4 ,1, 41
UNION ALL 
SELECT 2, 4 ,0, 42
UNION ALL 
SELECT 2, 4, 0, 43
UNION ALL 
SELECT 2, 4, 0, 44
UNION ALL 
SELECT 2, 4, 0, 54
UNION ALL 
SELECT 2, 5, 1, 60
UNION ALL 
SELECT 2, 5, 0, 61
UNION ALL
SELECT 2, 5, 0, 62
UNION ALL 
SELECT 2, 6, 1, 65
UNION ALL 
SELECT 3, 7, 1, 68
UNION ALL 
SELECT 3, 7, 0, 69
UNION ALL 
SELECT 3, 7, 0, 70
UNION ALL 
SELECT 3, 7, 0, 71
UNION ALL 
SELECT 3, 7, 0, 72
UNION ALL 
SELECT 3, 7, 0, 73
UNION ALL 
SELECT 3, 7, 0, 74
UNION ALL 
SELECT 4, 8, 1, 75
UNION ALL 
SELECT 4, 9, 1, 76
UNION ALL 
SELECT 5, 10, 1, 80
UNION ALL 
SELECT 6, 11, 1, 81


SELECT * from @T


Где [order] - это номер заказа, как правило в номере заказа все люди - это одна семья или люди купившие вместе билеты, и они хотят сидеть рядом
[category] - это признак взрослый =1 или ребенок =0. Т.е. если признак = ребенок, то ему нужен сопровождающий взрослый, который будет как правило сидеть в одной заявке [order] , и соответственно сидеть рядом
[id] - это как раз признак, показывающий связь ребенка с одним из взрослых, т.к. в одной заявке [order] могут находиться две семьи
[People] - это id человека, не повторяющаяся величина.

Есть ограничение по рассадке: в семье может находиться не более 6 человек, если больше 6, то эту семью надо делить на части.

Нужно отранжировать рассадку людей по местам, согласно правилам.

т.е. получить в итоге таблицу вида:

order id categorypeopleseatsblock
1 1 1 561
1 2 1 571
1 3 1 451
2 4 1 412
2 4 0 422
2 4 0 432
2 4 0 442
2 4 0 542
2 5 1 603
2 5 0 613
2 5 0 623
2 6 1 653
3 7 1 684
3 7 0 694
3 7 0 704
3 7 0 714
3 7 0 724
3 7 0 734
3 7 0 745
4 8 1 755
4 9 1 765
5 10 1 806
6 11 1 817


Поле SeatsBlock - это как раз деление по 6 человек на рассадку , у кого одинаковый seatsblock, система им присвоит идущие подряд номера мест. Смысл заключается в том, я мог бы их отправлять по номерам [Order], но тут есть ограничения, в одном [order] могут находиться не более 6 человек и я должен этот [order] поделить так, чтобы дети не разделились со взрослыми, сложность заключается в том, предусмотреть случай, если мама летит с 6 детьми (ну или не мама, группа детей куда-то летит с одним взрослым), то получается 6 детей+ 1 взрослый, система выдаст ошибку, что в одном блоке мест не может находиться больше 6 человек.
В этом случае, мы одного ребенка цепляем другому свободному взрослому (или не свободному, у кого детей меньше 6) из этой заявки [order], если в этой заявке уже нет взрослых, то цепляем этого ребенка к свободному взрослому из след.заявки.

Надеюсь норм расписал, в общих чертах получается, загружаем по [order], но если в [order] больше 6 человек, то делим заявку таким образом, чтобы дети не разделились от взрослых. и второе в люди находящиеся в одном [order] должны сидеть рядом.

помогите с таким ранжированием.
26 ноя 18, 17:55    [21745255]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
TaPaK
Member

Откуда: Kiev
Сообщений: 5671
minya13_85,

Алгоритмы рюкзака?
26 ноя 18, 20:45    [21745422]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
aleks222
Member

Откуда:
Сообщений: 335
TaPaK
minya13_85,

Алгоритмы рюкзака?

Ответ неверный.
Садись. Неуд.
27 ноя 18, 05:32    [21745624]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
PizzaPizza
Member

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

Есть ощущение, что проблема именно в граничных случаях типа

minya13_85
если мама летит с 6 детьми (ну или не мама, группа детей куда-то летит с одним взрослым), то получается 6 детей+ 1 взрослый, система выдаст ошибку, что в одном блоке мест не может находиться больше 6 человек.
В этом случае, мы одного ребенка цепляем другому свободному взрослому (или не свободному, у кого детей меньше 6) из этой заявки [order], если в этой заявке уже нет взрослых, то цепляем этого ребенка к свободному взрослому из след.заявки.


И это уже работа не с наборами данных, а с отдельными записями, что в sqlе не рекомендуется делать. Перекидывание отдельных записей по условиям это проще в приложении сделать на любом языке который с массивами работать умеет.
27 ноя 18, 07:37    [21745655]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
982183
Member

Откуда: VL
Сообщений: 2482
Это не задача SQL.
27 ноя 18, 07:59    [21745659]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
minya13_85
Member

Откуда: Москва
Сообщений: 589
982183
Это не задача SQL.


Я все таки думаю можно ее решить на SQL. Типа такого, только надо немного доработать запрос. Тут главное условие как поделить сверхблок по 6
SELECT b.[order],b.id,b.category,b.people,DENSE_RANK() OVER(ORDER BY [b].[order],b.r) AS seatsblock
FROM 
(
SELECT a.[order],a.id,a.category,a.people, CASE WHEN a.r>6 THEN 0 ELSE 1 END AS r
FROM 
(
SELECT [order],id,category,people,COUNT(*) OVER(PARTITION BY [order]) AS r
FROM @T
) AS a
) AS b
27 ноя 18, 10:43    [21745786]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
Cristiano_Rivaldo
Member

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

Обыкновенная разноска. Посмотри тут - разноска с ограничением
27 ноя 18, 11:11    [21745809]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
982183
Member

Откуда: VL
Сообщений: 2482
А потом понадобится отделить мужчин от женщин.
А затем мусульман от христиан.
И снова будем приделывать ДВС к велосипеду.
28 ноя 18, 03:59    [21746751]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2107
minya13_85
982183
Это не задача SQL.


Я все таки думаю можно ее решить на SQL.
Можно и гвозди микроскопом забивать, но зачем??
28 ноя 18, 04:00    [21746752]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
aleks222
Member

Откуда:
Сообщений: 335
Mind
minya13_85
пропущено...


Я все таки думаю можно ее решить на SQL.
Можно и гвозди микроскопом забивать, но зачем??


Думаешь "на клиенте" тредстартер сможет?
Хе-хе. Если человек не может сделать на одном языке программирования - он не сможет сделать ни на одном языке программирования.

Задача вполне тривиальна.

1. [order] не более 6 чел суем в один seatsblock.
2. [order] более 6 чел сортируем по порядку: дите1, дите2... дитеN, взрослый1, дитеN+1, дитеN+2, дитеN+N, взрослый2, ...., где N = числодетей/числовзрослых. Если N>5 - ничо поделать низзя. Сортировать, если подумать, не обязательно.
3. Шинкуем по 6 чел.
28 ноя 18, 06:32    [21746762]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
982183
Member

Откуда: VL
Сообщений: 2482
Mind
Можно и гвозди микроскопом забивать, но зачем??

Ну например, если другие средства и персоналии разработки отсутствуют.
А задача не критична и решаема (хоть и криво) стандартными, проверенными, отработанными методами.
28 ноя 18, 09:03    [21746833]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 5951
Если куры денег не клюют, можно и подороже СУБД найти. А можно и бесплатным средством реализовать с лучшей производительностью к тому же.
28 ноя 18, 12:09    [21747108]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
DaniilSeryi
Member

Откуда:
Сообщений: 1270
Так вот почему авиакомпания Победа раньше людей автоматически в случайном порядке рассаживала! Неужели решили решить эту проблему???
29 ноя 18, 12:58    [21748442]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
Cristiano_Rivaldo
Member

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

;WITH tt ([ORDER],id,category,people,N,N_Places_Remn,B_With_Adult)
AS
(
	SELECT	t.*,		
			MAX(CASE WHEN t.category = 1 THEN 1 ELSE 0 END ) OVER ( PARTITION BY t.[order],t.N / 7)   B_With_Adult -- признак закрепления за взрослым
	FROM (
			SELECT	t.*,
					COUNT(*) OVER (PARTITION BY  t.[order] ORDER BY t.[order],t.id, t.category DESC , t.people )  N, -- для определения SeatsBlock
					5 - COUNT(CASE WHEN t.category = 0 THEN 1 END ) OVER (PARTITION BY t.id)	N_Places_Remn	 -- остаток свободных мест для детей
			from @T t
	) t
)

SELECT  t.*,
		DENSE_RANK() OVER (ORDER BY ISNULL(t.new_order,t.[order]),t.N_New / 7)	AS 	SeatsBlock
FROM (
		SELECT  t.*,
				COUNT(*) OVER (PARTITION BY  ISNULL(t.new_order,t.[order]) ORDER BY ISNULL(t.new_order,t.[order]),isnull(t.new_id,t.id), t.category DESC , t.people ) N_New
		FROM (
						-- распределение по взрослым
						SELECT  r.[order],r.id,r.category,r.people
								,v.[order] new_order,v.id new_id
						FROM (
								SELECT	tt.*,
										ROW_NUMBER() OVER (ORDER BY (SELECT 1)) N_B_With_Adult
								FROM tt 
								WHERE tt.B_With_Adult = 0
							) R
							INNER JOIN 
							(
								SELECT  rr.[order],
										rr.ID,
										ROW_NUMBER() OVER (ORDER BY (SELECT 1)) N_B_With_Adult
								FROM (
										SELECT	tt.[order],tt.id,tt.N_Places_Remn
										FROM tt 
										WHERE -- заявка либо текущая,либо следующая
											tt.[ORDER] >= 
											(
												SELECT TOP 1 rr.[ORDER] 
												FROM tt  rr
												WHERE rr.B_With_Adult = 0
												ORDER BY rr.[ORDER] 
											)
										  AND 	tt.N_Places_Remn > 0
										 GROUP BY  tt.[order],tt.id,tt.N_Places_Remn
								  ) rr
								  -- разбивка на строки - количество свободных мест для детей
								  CROSS APPLY 
									(
										 SELECT NULL  N
										 FROM 
										 (SELECT 1 N UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5) kk
										 WHERE kk.N <=  rr.N_Places_Remn
									) h
							) V
							 ON r.N_B_With_Adult = v.N_B_With_Adult

						UNION ALL	 
						-- без распределения (as is)
						SELECT	 r.[order],r.id,r.category,r.people,NULL,NULL
						FROM tt  r
						WHERE r.B_With_Adult = 1
		) t
) t
5 дек 18, 13:34    [21754306]     Ответить | Цитировать Сообщить модератору
 Re: Рассадка по местам в самолете  [new]
Mind
Member

Откуда: Лучший город на Земле
Сообщений: 2107
982183
Mind
Можно и гвозди микроскопом забивать, но зачем??

Ну например, если другие средства и персоналии разработки отсутствуют.
А задача не критична и решаема (хоть и криво) стандартными, проверенными, отработанными методами.
То есть пофигу на людей которые потом будут читать, искать ошибки и поддерживать это Г-но?
5 дек 18, 20:38    [21754957]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить