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

Откуда:
Сообщений: 127
На данный момент БД под управление MS SQL Server 2000.
Есть таблица:
Key...ДатаВремя
1...2015010108:08:08
2...2015010119:20:18
............
n...2015010120:20:20
n+1...2015010200:20:18
............

Поле Дата - тип nvarchar(12) формат "yyyymmdd"
Поле Время - тип nvarchar(10)формат "чч:мм:сс"
Форматы хранения данных хоть и указаны, но с одной стороны - контролируются они только лишь в клиентской части приложения, с другой - с некорректностью данных за 5 лет проблем не было.
"Физически" смысл данных в таблице: Есть Объемы чего либо, которые "возникли" в момент Дата и Время. Поле Дата это обычная календарная дата момента "возникновения" объемов, но фильтровать обрабатываемые в запросах данные надо по принадлежности объемов к рабочей смене. Например: "Вывести объемы за 1-ю смену, 02.02.2015". Смена, в свою очередь, это вычисляемая величина, зависящая от значений поля Дата и Смена. Смены 2-ве, 1-я смена - с '20:00:00'(включительно) до '08.00.00'(не входит), 2-я ... , думаю понятно, все как обычно при двухсменном графике. Причем ВСЯ смена датируется ОДНОЙ датой. Для второй смены и так все понятно. А к данным за 1-ю смену, 02.02.2015, относятся и данные с '20:00:00' '01.01.2015' до конца суток. И как уже говорил ранее фильтровать данные необходимо по смене. (Разумность хранения сразу "правильной" даты не обсуждается).
На данный, во всех известных мне "местах"(хранимых процедурах), при обращении к данным используется следующая конструкция:
@Смена, @Дата - входные параметры
 
@ПредыдущаяДата = ONVERT(nvarchar(12), DATEADD(DAY, -1, @Дата ), 112) --DECLARE @ПредыдущаяДата nvarchar(12)
IF @Смена = 1 BEGIN
	SELECT
	...
	WHERE
		(Дата = @Дата) AND ((DATEPART(HOUR, Время) < 20) AND (DATEPART(HOUR, Время) >= 8)) --вторая смена
ELSE
	SELECT
	...
	WHERE
		((Дата = @ПредыдущаяДата) AND ((DATEPART(HOUR, Время) < 24) AND (DATEPART(HOUR, Время)>=20)) --Вечер, предыдущих запрошенным суток, первой смены.
		OR ((Дата = @Дата)	AND (DATEPART(HOUR, Время) < 8)) --Утро, запрошенным суток, первой смены. 

В общем, не нравится мне это огромное число повторяющегося кода, неудобно. Решил постепенно переделать.
Пусть первый вариант будет то что описано выше.
Второй вариант:
 SELECT 
	...
	WHERE
		 @Смена= (case when (DATEPART(HOUR, Время) < 20) AND (DATEPART(HOUR, Время) >= 8) then 2 else 1 end)
		AND @Дата= (case when (DATEPART(HOUR, Время) >= 20) AND (DATEPART(HOUR, Время) < 24) then CONVERT(nvarchar(12),DATEADD(DAY,+1, Дата),112) else Дата end)
--Самый медленный (но производительность проверял, так по примитивному, т.к. нет знаний и опыта)
Третий вариант:
Создать два вычисляемых поля
CREATE TABLE [Таблица] (... ,
	[Дата] [nvarchar] (12) ,
	[Время] [nvarchar] (10),
	[СменаНомер] AS (case when ([Время] < '20:00:00' and ([Время] >= '08:00:00')) then 2 else 1 end) ,
	[СменаДата] AS (case when ([Время] >= '20:00:00' and ([Время] < '24:00:00')) then (convert(nvarchar(12),dateadd(day,1,[Дата]),112)) else [Дата] end) 
) 

Третий вариант нравится больше т.к. - Создал поля и не надо дальше в запросах беспокоится об приведении дат.
ПЕРВЫЙ ВОПРОС
Но если DATEPART(HOUR, Время) < 20 гарантирует надежность при всех явных и не явных установках формата ... то
[Время] < '20:00:00' ??? Вот тут и первый вопрос - как бы это не то что бы type DateTime, а даже не время? а строка и чем опасна такое сравнение, разобраться ни хватает ни знаний не опыта. Помогите пожалуйста.
ВТОРОЙ ВОПРОС
Насколько опасно для производительности использование вычисляемых полей в моем случае?
Собственные рассуждения:
Да первый вариант будет побыстрей т.к. необходимо меньше преобразований над данными. Но получить преимущества от индексов по полям Дата и Время не получится т.к. DATEPART(HOUR, Время) в условиях. Третий вариант помедленнее, но планируется переход на ms SQL 2008 где я смогу сделать вычисляемые поля с пометкой PERSISTED и создать индексы.
В общем не хватает понять самому что стоит что не стоит и как лучше!
29 дек 15, 14:07    [18623001]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить