powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите пожалуйста оценить решение тестового задания
24 сообщений из 24, страница 1 из 1
Помогите пожалуйста оценить решение тестового задания
    #39997183
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте, проходил тестовые задания одной из фирм. В результате получил следующий ответ "К сожалению тест не прошел, видимо пока не достаточно опыта", стало интересно в каком конкретно месте я затупил. Очень прошу оценить решение ребят которые хорошо знают t-sql. Для себя на будущее и для развития
Если кто поможет, прошу к своему мнению добавить устроил бы их как руководителя такой ответ (то есть прошел тестовые задания или нет)

Задачи и их решение приложил файлами
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997184
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997185
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997219
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,

автор1. Высчитать сумму всех цифр серии и номера паспорта (На входе получаем текст, состоящий из серии и номера паспорта, разделенных пробелом,
например, «1234 567890». На выходе должно получиться число меньше десяти. Пример: 1+2+3+4+5+6+7+8+9+0 = 45 = 4+5 = 9
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select top 10 FirstName, Surname, LastName, Number, ReceiveDate
from #Documents d
cross apply (select Num
				   ,0 + LEFT('0'+Num,1) + RIGHT('0'+Num,1) as sm
			 from (select 0 + SUBSTRING(Number,1,1) + SUBSTRING(Number,2,1) + SUBSTRING(Number,3,1) + SUBSTRING(Number,4,1)
				            + SUBSTRING(Number,5,1) + SUBSTRING(Number,6,1) + SUBSTRING(Number,7,1) + SUBSTRING(Number,8,1)
					        + SUBSTRING(Number,9,1) + SUBSTRING(Number,10,1) as Num
			       from (select REPLACE(d.Number,' ','') as Number) A
				  )A
			 where 0 + LEFT('0'+Num,1) + RIGHT('0'+Num,1) < 10
			) Num
where Num % 2 = 0
order by ReceiveDate



Твой cross apply не выполняет выделенное условие.
Сумма 10-ти цифр, может дать число, сумма цифр которого будет больше 10.
Например - 9999 988888 => 85 => 13 = > 4 (т.е. тут 3-и суммирования нужно сделать)
Вот гражданин с таким номером, просто не поучаствует в розыгрыше ...
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997220
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

Решения в файлах ваши или работодателя?
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997227
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор1. Высчитать сумму всех цифр серии и номера паспорта (На входе получаем текст, состоящий из серии и номера паспорта, разделенных пробелом,
например, «1234 567890». На выходе должно получиться число меньше десяти. Пример: 1+2+3+4+5+6+7+8+9+0 = 45 = 4+5 = 9
Да тут просто порезать на два числа, сложить их, и поделить на 9. Остаток (если он ноль - заменить на 9) и есть ответ.

Это даже не на знание SQL, это школьная математика. А здесь как в анекдоте "а вы такое написали! да ещё и нарисовали!".
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997229
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторНаписать скрипт на выборку сумм по продажам товаров со следующими условиями:
• Выводить суммы продаж за указанный пользователем период (любой)
• В строки выводить наименование товаров, сумму продаж за указанную дату, при этом т.к. период выборки может меняться, количество колонок в итоговом отчете заранее неизвестно.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
declare @SQL VARCHAR(max) = 'select p.ProductName'

declare @dt date
SET @dt = @DateBegin

WHILE @dt <= @DateEnd
BEGIN
	SET @SQL += '
				,(select SUM(f.quantity)
				  from #Fin1 f
				  where f.recdate = '''+CONVERT(varchar,@dt,112)+'''
				    and f.product_id = p.tid) as ['+CONVERT(varchar,@dt,104)+']
				'
	SET @dt = DATEADD(DAY,1,@dt)
END

SET @SQL += '

from #Products p'



тут - "да", без динамики не обойтись, но, имхо, 100500 коррелированных подзапросов, это как-то "жестоко" ...
Динамический pivot или 'sum(case when recdate=' + @dt + ' then quantity end) as ... ' смотрелись бы получше

+ твой запрос будет выводить всегда все товары, вне зависимости от того, были ли продажи в этот период.
Из постановки, этот момент не совсем ясен (совсем не ясен), нужно ли всегда выводить весь справочник, но логичнее всё-таки выводить только то, по чем были продажи ...
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997234
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,
спасибо огромное за комментарии

1. по сумме
Код: sql
1.
2.
3.
4.
select 0 + SUBSTRING(Number,1,1) + SUBSTRING(Number,2,1) + SUBSTRING(Number,3,1) + SUBSTRING(Number,4,1)
				            + SUBSTRING(Number,5,1) + SUBSTRING(Number,6,1) + SUBSTRING(Number,7,1) + SUBSTRING(Number,8,1)
					        + SUBSTRING(Number,9,1) + SUBSTRING(Number,10,1) as Num
			       from (select REPLACE(d.Number,' ','') as Number) A


Это посчитает сумму 85
Код: sql
1.
0 + LEFT('0'+Num,1) + RIGHT('0'+Num,1)


это условие 8+5 < 10
Насколько я понял из условия задачи таких как раз нужно исключать. Я неверно понял задание?

2. 'sum(case when recdate=' + @dt + ' then quantity end) as ... ' смотрелись бы получше
ты прав, не додумался

+ твой запрос будет выводить всегда все товары, вне зависимости от того, были ли продажи в этот период.
Из постановки, этот момент не совсем ясен (совсем не ясен), нужно ли всегда выводить весь справочник, но логичнее всё-таки выводить только то, по чем были продажи ...

так и планировал, думал если отчет, то должен показать статистику по всем товарам, чтобы было видно какой товар вообще не участвовал.
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997237
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist
Насколько я понял из условия задачи таких как раз нужно исключать. Я неверно понял задание?
думаю, что не правильно.
Иначе было бы сказано явно, про то, что их нужно исключить
(+ это известный "алгоритм" у всяких "нумерологических гаданий" :)) когда сложение цифр идет до получения итоговой цифры, т.е. < 10)

пс
нуу и Akina , видимо, "зрит в корень" :) - задача была на знание этого алгебр."свойства"
Код: sql
1.
2.
3.
select (99999+88888) % 9
-----------
4
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997269
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist,

3-я интересная
только я её, в случае ID=6 и 7, понял не так как ты
имхо, конечно, думаю что тут имеется в виду, что мы не знаем какое из продублированных "Отбытие" (6) и "Прибытие" (7) правильное
Поэтому берём среднее от обоих вариантов
Код: 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.
-- Рассчитать среднее время в пути в разрезе транспорта
if OBJECT_ID('tempdb..#t') is not null drop table #t
create table #t(ID int, date smalldatetime, Reason varchar(8))
insert into #t (ID, date, Reason)
values (1,	'20180721 11:00',	'Отбытие')
      ,(1,	'20180721 18:00',	'Прибытие')
      ,(1,	'20180812 14:40',	'Отбытие')
      ,(1,	'20180812 19:20',	'Прибытие')
      ,(1,	'20180813 10:00',	'Отбытие')
      ,(1,	'20180814 08:10',	'Прибытие')
      ,(2,	'20180919 12:00',	'Отбытие')
      ,(2,	'20180919 12:15',	'Прибытие')
      ,(3,	'20180924 11:00',	'Отбытие')
      ,(3,	'20180925 16:00',	'Прибытие')
      ,(3,	'20180930 16:00',	'Отбытие')
      ,(3,	'20181002 11:40',	'Прибытие')	  
	  --Пример транспорт в пути
	  ,(4,	'20180901 20:00',	'Отбытие')
	  ,(4,	'20180904 10:00',	'Прибытие')
	  ,(4,	'20180904 20:00',	'Отбытие')
	  --Пример обрезали по времени некорректно
	  ,(5,	'20200101 20:00',	'Прибытие')
	  ,(5,	'20200102 20:00',	'Отбытие')
	  ,(5,	'20200103 20:00',	'Прибытие')
	  --Пример некорректно: транспорт 2 раза отбыл прежде чем прибыть
	  ,(6,	'20200101 20:00',	'Отбытие')
	  ,(6,	'20200102 20:00',	'Отбытие')
	  ,(6,	'20200103 20:00',	'Прибытие')
	  --Пример некорректно: транспорт 2 раза прибыл отбыв единожды
	  ,(7,	'20200101 20:00',	'Отбытие')
	  ,(7,	'20200102 20:00',	'Прибытие')
	  ,(7,	'20200103 20:00',	'Прибытие')


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
;with cte as (
	select 
		*
		,ROW_NUMBER()over(partition by ID order by date) - ROW_NUMBER()over(partition by ID, Reason order by date) as flag
	from #t t1
	where exists (select 1 from #t t2 where t1.ID=t2.ID and t1.Reason='Прибытие' and t2.Reason='Отбытие' and t1.date>t2.date) or t1.Reason='Отбытие'),
cte1 as (
	select
		*
		,dense_rank()over(partition by ID, Reason order by flag) as num_flight
	from cte)

--select * from cte1 order by 1,2

select
	dep.ID 
	,AVG(DATEDIFF(MINUTE,dep.date,arr.date))
from cte1 dep inner join cte1 arr on dep.ID = arr.ID and dep.num_flight = arr.num_flight 
where dep.Reason = 'Отбытие' and arr.Reason = 'Прибытие'
group by dep.ID
order by 1


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

еще раз спасибо огромное!
в 3 задаче не было пунктов 4,5,6,7 - это я додумал, что в принципе такое может быть и как по мне это ошибка, не может транспорт 2 раза подряд отбыть, соответственно по сути не важно какое решение по таким случая, главное чтобы не ошибочное (в плане реализации ты подумал о них)

насчет select (99999+88888) % 9
объясните мне пожалуйста суть, я что-то никак не могу уловить что требовалось
"Высчитать сумму всех цифр серии и номера паспорта (На входе получаем текст, состоящий из серии и номера паспорта, разделенных пробелом, например, «1234 567890». На выходе должно получиться число меньше десяти. Пример: 1+2+3+4+5+6+7+8+9+0 = 45 = 4+5 = 9"

Я понял, что не нужно было фильтровать по этому значению, а просто вывести цифру как отдельное поля для того чтобы показать что ты знаешь какой-то алгоритм "со школьной математики" )) но не могу понять для чего и в чем задача? сделать так, чтобы суммируя 10 чисел ты по итогу получил цифру?
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997297
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist
сделать так, чтобы суммируя 10 чисел ты по итогу получил цифру?

да, именно так
суммировать пока не получится цифра (0-9)

А через формулу, которую написал Akina это делается просто и быстро
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
select (99999+88888) % 9
-----------
4

select (9999+988888) % 9
-----------
4

select (99+99+98+88+88) % 9
-----------
4

select (9+9+9+9+9+8+8+8+8+8) % 9
-----------
4
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997360
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,
то есть результат должен был быть таким?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select top 10 p1, num, FirstName, Surname, LastName, Number, ReceiveDate
from #Documents d
cross apply (select Num
				   ,IIF(Num % 9 = 0,9,Num % 9) as p1
			 from (select 0 + SUBSTRING(Number,1,1) + SUBSTRING(Number,2,1) + SUBSTRING(Number,3,1) + SUBSTRING(Number,4,1)
				            + SUBSTRING(Number,5,1) + SUBSTRING(Number,6,1) + SUBSTRING(Number,7,1) + SUBSTRING(Number,8,1)
					        + SUBSTRING(Number,9,1) + SUBSTRING(Number,10,1) as Num
			       from (select REPLACE(d.Number,' ','') as Number) A
				  )A
			) Num
where Num % 2 = 0
order by ReceiveDate



все равно ведь считать сумму цифр, от нее и получить цифру менее 10 по алгоритму Akina, верно?
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997371
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist
court,
то есть результат должен был быть таким?
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
select top 10 p1, num, FirstName, Surname, LastName, Number, ReceiveDate
from #Documents d
cross apply (select Num
				   ,IIF(Num % 9 = 0,9,Num % 9) as p1
			 from (select 0 + SUBSTRING(Number,1,1) + SUBSTRING(Number,2,1) + SUBSTRING(Number,3,1) + SUBSTRING(Number,4,1)
				            + SUBSTRING(Number,5,1) + SUBSTRING(Number,6,1) + SUBSTRING(Number,7,1) + SUBSTRING(Number,8,1)
					        + SUBSTRING(Number,9,1) + SUBSTRING(Number,10,1) as Num
			       from (select REPLACE(d.Number,' ','') as Number) A
				  )A
			) Num
where Num % 2 = 0
order by ReceiveDate




все равно ведь считать сумму цифр, от нее и получить цифру менее 10 по алгоритму Akina, верно?

проще
Код: sql
1.
2.
3.
4.
5.
select top 10 FirstName, Surname, LastName, a.Number, ReceiveDate
from #Documents d
cross apply (select case when cast(REPLACE(d.Number,' ','') as bigint) % 9 = 0 then 9 else cast(REPLACE(d.Number,' ','') as bigint) % 9 end as Number) a
where a.Number % 2 = 0
order by ReceiveDate
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997373
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist
все равно ведь считать сумму цифр

можно не разбивать на слагаемые / не считать сумму если получающееся число "влазит" в целочисленный тип
вот 10 символов (цифр) в bigint "влазит"
было бы больше - нужно было бы "разделить" на несколько слагаемых
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997389
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

спасибо, теперь у меня сложилась картина, для чего мы считали эту цифру, получается по ней и смотрим четное или нет


насчет второго задания, реализовал через pivot, ранее не делал через pivot стало интересно, посмотри плз

Код: 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.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
--!!! После слова например у меня не было примера, надеюсь, что правильно понял задачу
declare @DateBegin date
	   ,@DateEnd date
	   ,@N_Days int

SET @DateBegin = '20200801'
SET @DateEnd   = '20200904'

	IF   @DateBegin is null OR @DateEnd is null
	  OR @DateBegin > @DateEnd
	BEGIN
		SELECT @DateBegin = CONVERT(DATE,GETDATE())
			  ,@DateEnd   = CONVERT(DATE,GETDATE())
		--ну вообще return 0
	END

SET @N_Days = DATEDIFF(DAY,@DateBegin,@DateEnd)

	--Макс кол столбцов на выдачу в SQL SERVER x64 = 4096
	IF @N_Days > 4095 
	BEGIN
		SET @N_Days = 4095
		--ну вообще return 0
	END

if OBJECT_ID('tempdb..#Products') is not null drop table #Products
create table #Products (tid  int primary key identity(1,1)
                       ,productName varchar(max) not null)
insert into #Products (productName)
select LEFT(CONVERT(VARCHAR(36),NEWID()),15) as FirstName
from       (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t1(r) --       10
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t2(r) --      100
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t3(r) --    1 000

if OBJECT_ID('tempdb..#Sales') is not null drop table #Sales
create table #Sales (tid int primary key identity (-2147483648,1)
			        ,product_id int not null
					,quantity float not null
					,recdate datetime not null)
insert into #Sales (product_id, quantity, recdate)
select ABS(CHECKSUM(NEWID())) % 1000 as product_id
	  ,ABS(CHECKSUM(NEWID())) % 100 as quantity
	  ,DATEADD(HOUR,-ABS(CHECKSUM(NEWID())) % DATEDIFF(HOUR,'20180101',GETDATE()),GETDATE()) as ReceiveDate
from       (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t1(r) --       10
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t2(r) --      100
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t3(r) --    1 000
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t4(r) --   10 000
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t5(r) --  100 000
--cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t6(r) --1 000 000

if OBJECT_ID('tempdb..#Days') is not null drop table #Days
create table #Days (D date)
insert into #Days (D)
select DATEADD(DAY,-(t1.d*1000+t2.d*100+t3.d*10+t4.d),@dateEnd)D
from       (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t1(d) --       10
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t2(d) --      100
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t3(d) --    1 000
cross join (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9))t4(d) --   10 000
where t1.d*1000+t2.d*100+t3.d*10+t4.d <= @N_Days

if OBJECT_ID('tempdb..#Fin1') is not null drop table #Fin1
create table #Fin1 (product_id int, recdate varchar(10), quantity float, primary key (product_id, recdate))
insert into #Fin1 (product_id, recdate, quantity)
select p.tid, CONVERT(VARCHAR(10),d.D,104) as recdate
	  ,ISNULL(SUM(s.quantity),0) as quantity
from #Days d
cross join #Products p
left join #Sales s on s.recdate >= d.D 
				  AND s.recdate < DATEADD(DAY,1,d.D)
				  AND s.product_id = p.tid
where d.D >= @DateBegin
  AND d.D < DATEADD(DAY,1,@DateEnd)
group by p.tid, d.D

declare @SQL varchar(max)
	   ,@days varchar(max)

select @days = STUFF((select [text()] = ',['+CONVERT(varchar(10),D,104)+']'
				      from #Days
					  order by D
					  for xml path('')
				      ),1,1,'')

SET @SQL = 'SELECT ProductName, '+@days+'
			FROM #Products p
			LEFT JOIN #Fin1 f on p.tid = f.product_id
			PIVOT (SUM(quantity) for recdate in ('+@days+')) pvt
		  '

--В строки выводить наименование товаров, сумму продаж за указанную дату, при этом т.к. период выборки может меняться, количество колонок в итоговом отчете заранее неизвестно.
EXEC (@SQL)
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997396
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sandist
насчет второго задания
да, я бы так и делал
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997400
Sandist
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court,

огромнейшее спасибо )))

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

Не расстраивайтесь. Работодатель, который предлагает задачи предполагающие SUBSTRINGSUBSTRINGSUBSTRINGSUBSTRINGSUBSTRING в решении или иное извращенное применение sql в качестве парсеров и разбирателей куч пахнущей субстанции вместо данных, не стоит внимания.
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997665
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court
Sandist,

3-я интересная
только я её, в случае ID=6 и 7, понял не так как ты
имхо, конечно, думаю что тут имеется в виду, что мы не знаем какое из продублированных "Отбытие" (6) и "Прибытие" (7) правильное
Поэтому берём среднее от обоих вариантов
Код: 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.
-- Рассчитать среднее время в пути в разрезе транспорта
if OBJECT_ID('tempdb..#t') is not null drop table #t
create table #t(ID int, date smalldatetime, Reason varchar(8))
insert into #t (ID, date, Reason)
values (1,	'20180721 11:00',	'Отбытие')
      ,(1,	'20180721 18:00',	'Прибытие')
      ,(1,	'20180812 14:40',	'Отбытие')
      ,(1,	'20180812 19:20',	'Прибытие')
      ,(1,	'20180813 10:00',	'Отбытие')
      ,(1,	'20180814 08:10',	'Прибытие')
      ,(2,	'20180919 12:00',	'Отбытие')
      ,(2,	'20180919 12:15',	'Прибытие')
      ,(3,	'20180924 11:00',	'Отбытие')
      ,(3,	'20180925 16:00',	'Прибытие')
      ,(3,	'20180930 16:00',	'Отбытие')
      ,(3,	'20181002 11:40',	'Прибытие')	  
	  --Пример транспорт в пути
	  ,(4,	'20180901 20:00',	'Отбытие')
	  ,(4,	'20180904 10:00',	'Прибытие')
	  ,(4,	'20180904 20:00',	'Отбытие')
	  --Пример обрезали по времени некорректно
	  ,(5,	'20200101 20:00',	'Прибытие')
	  ,(5,	'20200102 20:00',	'Отбытие')
	  ,(5,	'20200103 20:00',	'Прибытие')
	  --Пример некорректно: транспорт 2 раза отбыл прежде чем прибыть
	  ,(6,	'20200101 20:00',	'Отбытие')
	  ,(6,	'20200102 20:00',	'Отбытие')
	  ,(6,	'20200103 20:00',	'Прибытие')
	  --Пример некорректно: транспорт 2 раза прибыл отбыв единожды
	  ,(7,	'20200101 20:00',	'Отбытие')
	  ,(7,	'20200102 20:00',	'Прибытие')
	  ,(7,	'20200103 20:00',	'Прибытие')


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
;with cte as (
	select 
		*
		,ROW_NUMBER()over(partition by ID order by date) - ROW_NUMBER()over(partition by ID, Reason order by date) as flag
	from #t t1
	where exists (select 1 from #t t2 where t1.ID=t2.ID and t1.Reason='Прибытие' and t2.Reason='Отбытие' and t1.date>t2.date) or t1.Reason='Отбытие'),
cte1 as (
	select
		*
		,dense_rank()over(partition by ID, Reason order by flag) as num_flight
	from cte)

--select * from cte1 order by 1,2

select
	dep.ID 
	,AVG(DATEDIFF(MINUTE,dep.date,arr.date))
from cte1 dep inner join cte1 arr on dep.ID = arr.ID and dep.num_flight = arr.num_flight 
where dep.Reason = 'Отбытие' and arr.Reason = 'Прибытие'
group by dep.ID
order by 1


IDtAVG_On_Way_Min1t6762t153t21804t37205t14406t21607t2160


Ужос.
Прежде чем громоздить горы говнокода, надо азы математики вспомнить.

Для корректной постановки (отбытий и прибытий одинаково и они чередуются):

СреднееВремя = Сумма(Прибытие-Отбытие) / Число_отбытий

СреднееВремя = ( Сумма(Прибытие) - Сумма(Отбытие) ) / Число_отбытий

т.е. переводим даты в минуты (или секунды) относительно ЛЮБОЙ даты и фперде.


Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
declare @t table( ID int, date smalldatetime, Reason varchar(8));

insert into @t (ID, date, Reason)
values (1,	'20180721 11:00',	'Отбытие')
      ,(1,	'20180721 18:00',	'Прибытие')
      ,(1,	'20180812 14:40',	'Отбытие')
      ,(1,	'20180812 19:20',	'Прибытие')
      ,(1,	'20180813 10:00',	'Отбытие')
      ,(1,	'20180814 08:10',	'Прибытие')
      ,(2,	'20180919 12:00',	'Отбытие')
      ,(2,	'20180919 12:15',	'Прибытие')
      ,(3,	'20180924 11:00',	'Отбытие')
      ,(3,	'20180925 16:00',	'Прибытие')
      ,(3,	'20180930 16:00',	'Отбытие')
      ,(3,	'20181002 11:40',	'Прибытие')	  


select id, 2.0 * sum( ( case Reason when 'Отбытие' then -1 when 'Прибытие' then 1 end ) * datediff( minute, '20180101', [date] ) )  / count( *)
  from @t
  group by id
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997669
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleks222
Для корректной постановки (отбытий и прибытий одинаково и они чередуются):
нуу, а для "некорректной" ?
это всё "городилось" под это предположение

court
только я её, в случае ID=6 и 7, понял не так как ты
имхо, конечно, думаю что тут имеется в виду, что мы не знаем какое из продублированных "Отбытие" (6) и "Прибытие" (7) правильное
Поэтому берём среднее от обоих вариантов
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997671
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court
aleks222
Для корректной постановки (отбытий и прибытий одинаково и они чередуются):
нуу, а для "некорректной" ?
это всё "городилось" под это предположение

court
только я её, в случае ID=6 и 7, понял не так как ты
имхо, конечно, думаю что тут имеется в виду, что мы не знаем какое из продублированных "Отбытие" (6) и "Прибытие" (7) правильное
Поэтому берём среднее от обоих вариантов


А для некорректной - требуются доп. указания.
В постановке задачи их нет => все некорректные следует НЕ считать.
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997899
Фотография court
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleks222
court
пропущено...
нуу, а для "некорректной" ?
это всё "городилось" под это предположение

пропущено...


А для некорректной - требуются доп. указания.
В постановке задачи их нет => все некорректные следует НЕ считать.

а какое из 2-х "Отбытие" (6) и "Прибытие" (7) корректное, а какое некорректное ?
...
Рейтинг: 0 / 0
Помогите пожалуйста оценить решение тестового задания
    #39997901
aleks222
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
court
aleks222
пропущено...


А для некорректной - требуются доп. указания.
В постановке задачи их нет => все некорректные следует НЕ считать.

а какое из 2-х "Отбытие" (6) и "Прибытие" (7) корректное, а какое некорректное ?


Бессмысленные рассуждения в контексте тестовой задачи.
В реальности это вне компетенции программиста.
Начальство должно решить "чаво делать с некорректными данными?".
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Помогите пожалуйста оценить решение тестового задания
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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