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

Откуда: Москва
Сообщений: 873
автор
Задача 1
Есть таблица UDFs с колонками UDFName , UdfValue, Date.
Первичный ключ - (UDFName, Date)
UDFName может иметь три значения - “V”, “Border1”, “Border2”.
Требуется написать запрос, который выдаст количество записей следующего типа.
Значение в колонке UDFValue соответствующее V должно располагаться между значениями соответствующими Border1 и Border2 в рамках одной даты.


Табличка UDFs

create table UDFs 
(
udfname nvarchar(250),
udfvalue float,
[date] date,
primary key(date,udfname)
) 

GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'V', 10, CAST(N'2013-10-10' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'Border1', 5, CAST(N'2013-10-10' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'Border2', 20, CAST(N'2013-10-10' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'V', 10, CAST(N'2013-10-11' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'Border1', 50, CAST(N'2013-10-11' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'Border2', 70, CAST(N'2013-10-11' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'V', 10, CAST(N'2013-10-13' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'Border1', 10, CAST(N'2013-10-13' AS Date))
GO
INSERT [dbo].[UDFs] ([udfname], [udfvalue], [date]) VALUES (N'Border2', 10, CAST(N'2013-10-13' AS Date))
GO



Вот моё решение:
declare @udfd date, @b1 int, @b2 int, @v int, @count int
set @count = 0
DECLARE Employee_Cursor CURSOR FOR
SELECT distinct [date]
FROM dbo.UDFs

OPEN Employee_Cursor;

FETCH NEXT FROM Employee_Cursor into @udfd;
WHILE @@FETCH_STATUS = 0
BEGIN
	select @b1 = udfvalue from dbo.UDFs where [date] = @udfd and udfname = 'Border1'
	select @b2 = udfvalue from dbo.UDFs where [date] = @udfd and udfname = 'Border2'
	select @v = udfvalue from dbo.UDFs where [date] = @udfd and udfname = 'V'
	select @b1, @v, @b2 -- Выводим значения
	if (@b1 < @v and @v < @b2)
	begin
		set @count = @count +1
	end
    FETCH NEXT FROM Employee_Cursor into @udfd
END;

CLOSE Employee_Cursor;
DEALLOCATE Employee_Cursor;

select @count as [Условия задачи выполняются раз:]


Думаю, есть варианты более изящных решений.
6 май 16, 10:19    [19141322]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
iljy
Member

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

конечно есть. два раза джойн таблицы самой на себя, фильтр по нужному условию и COUNT(*).
6 май 16, 10:22    [19141339]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Glory
Member

Откуда:
Сообщений: 104751
автор
Требуется написать запрос, который выдаст количество записей следующего типа.

Какого "следующего типа" ?

автор
Значение в колонке UDFValue соответствующее V должно располагаться между значениями соответствующими Border1 и Border2 в рамках одной даты.

Так вывести "количество записей" или упорядочить все записи ?
6 май 16, 10:23    [19141350]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 21101
автор
Значение в колонке UDFValue соответствующее V должно располагаться между значениями соответствующими Border1 и Border2 в рамках одной даты.

А LEAD/LAG использовать можно?
6 май 16, 10:37    [19141420]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
invm
Member

Откуда: Москва
Сообщений: 9724
with s (V, Border1, Border2) as
(
 select
  max(case when udfname = 'V' then udfvalue end),
  max(case when udfname = 'Border1' then udfvalue end),
  max(case when udfname = 'Border2' then udfvalue end)
 from
  UDFs
 group by
  [date]
)
select count(*) from s where V between Border1 and Border2;
6 май 16, 10:52    [19141494]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 21101
invm
1Border1
2Border2
3V
4Border2
6 май 16, 11:02    [19141548]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Glory
Member

Откуда:
Сообщений: 104751
UNPIVOT и сравнение полей
6 май 16, 11:07    [19141583]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
invm
Member

Откуда: Москва
Сообщений: 9724
Akina,

И что вас смущает?
6 май 16, 11:08    [19141591]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
aleks2
Guest
teCa
Значение в колонке UDFValue соответствующее V должно располагаться между значениями соответствующими Border1 и Border2 в рамках одной даты.


Садитесь. Всем неуд.

Невозможно установить "между или нет" в пределах "даты" порядок не определен.
6 май 16, 17:24    [19143710]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 21101
invm, исключительно то, что такой набор записей не соответствует заданию, записи 1,3,4 будут Вашим запросом обработаны как группа, несмотря на то, что она не является слитной.
6 май 16, 17:29    [19143735]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
qwertEHOK
Member

Откуда: Волгоград
Сообщений: 273
select count(*) from UDFs u
left join (select * from UDFs where udfname='V') v on u.date=v.date
left join (select * from UDFs where udfname='Border1') b1 on u.date=b1.date
left join (select * from UDFs where udfname='Border2') b2 on u.date=b2.date
where u.udfname='v' and (u.udfvalue > b1.udfvalue) and u.udfvalue<b2.udfvalue


я вот так решил :)

а задание про удаление 3млрд записей у вас тоже было?
6 май 16, 17:51    [19143808]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
invm
Member

Откуда: Москва
Сообщений: 9724
Akina
записи 1,3,4 будут Вашим запросом обработаны как группа, несмотря на то, что она не является слитной.
А Вы внимательно посмотрели какой PK задекларирован у таблицы?
"Слитность" группы определяется датой. В Вашем наборе даты вообще нету.
6 май 16, 18:01    [19143847]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
buser
Member

Откуда: Санкт-Петербург
Сообщений: 4538
teCa, до кучи... менее эффективно, зато - молодежно
+
select count(*)
from @UDFs vs
		join (select [date], [Border1], [Border2] from @UDFs u pivot(max([udfvalue]) for [udfname] in ([Border1], [Border2])) piv) as border on vs.date = border.date 
where vs.udfname = 'V'
      and /* vs.udfvalue between border.Border1 and border.Border2 -- я, как и invm, как-то так представлял "между" */
	  vs.udfvalue > border.Border1 and vs.udfvalue < border.Border2



invm
"Слитность" группы определяется датой. В Вашем наборе даты вообще нету.

Не - там все пучком... в вхере всё ровняется
6 май 16, 18:45    [19143976]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 21101
invm, а разве не видно, что я даю схему, а не контент? Сразу в явной форме даю порядковый номер записи...
А некорректность исходной формулировки на принцип не влияет.
6 май 16, 22:08    [19144442]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
invm
Member

Откуда: Москва
Сообщений: 9724
Akina
invm, а разве не видно, что я даю схему, а не контент?
А не могли бы вы переложить вашу схему в контент, в рамках показанного ТС'ом DDL таблицы?
И пояснить зачем нужен порядковый номер и что такое слитная группа?
6 май 16, 22:39    [19144505]     Ответить | Цитировать Сообщить модератору
 Re: Еще один скрипт по тестовому заданию.  [new]
Col
Member

Откуда: Торонто
Сообщений: 182
teCa,

SELECT  u.DATE ,COUNT(*) 
FROM UDFs u
INNER  JOIN UDFs b1 ON (b1.udfname='Border1' and  u.DATE=b1.DATE)
INNER  JOIN UDFs b2 ON(b2.udfname='Border2' and u.DATE=b2.DATE)
WHERE u.udfname='V' AND u.udfvalue between b1.udfvalue AND b2.udfvalue
GROUP by u.DATE
7 май 16, 16:58    [19145918]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить