В 1С есть очень полезная фича — периодические реквизиты, с помощью них можно хранить не только значение, но и всю историю его изменения. Например, если мы храним значение курса бакса по отношению к рублю, то хранится не только актуальное значение, но и значение за вчера, позавчера и т.д.(период хранения может быть любой). В MySQL, к сожалению, такой фичи нет(наверное и не надо). Значит сделаем сами ;).
Рассмотрим на примере. Допустим у нас есть простейшая система заявок основанная на таблице TTroubleticket.
Кроме контактной информации и текста заявки необходимо хранить статус заявки со всей историей его изменений. Сразу напрашивается такое решение: хранить статус в другой таблице со всей историей изменений.
Тогда чтобы получить текущее значение нам надо выполнить следующий запрос:
Все складно, все хорошо, ничего лишнего, а при желании мы всегда сможем просмотреть всю историю изменений статуса. Первые трудности начнутся тогда, когда мы попытаемся получить значение на какую-нибудь дату. Поэтому добавим еще одно поле fedate — дата завершения действия значения. Пускай в этом поле будет храниться избыточная информация, но она нам оченьупростит жизнь пригодится.
Теперь чтобы получить значение на дату нам надо немного изменить запрос:
С этой сложностью справились. Но время идет, а система совершенствуется: нам понадобился такой параметр как тип заявки и тоже периодический. Фигня!-добавляем еще таблицу.
Зарос преобразуется:
И со временем у нас может появиться куча дополнительных таблиц, т.е. система усложняется, а в этом нет ничего хорошего.
Усовершенствуем наш подход — не будем создавать отдельные таблицы для каждой периодической переменной, все периодические переменные будем хранить в одной таблице.
Также, все актуальные значения будем хранить в основной таблице.
И теперь когда нам понадобится получить актуальные значения, нам достаточно выполнить простой запрос:
Ну, а если нам понадобится получить значения на дату, воспользуемся конструкцией LEFT JOIN:
Вот собственно и всё. Вроде бы получилось очень даже не сложное решение. А как вы храните периодические значения?
p.s. За идею спасибо А. Матвееву.
Рассмотрим на примере. Допустим у нас есть простейшая система заявок основанная на таблице TTroubleticket.
| Таблица TTroubleticket | |
| fkey | номер заявки |
| fcontact | контактная информация подавшего заявку |
| ftext | текст заявки |
Кроме контактной информации и текста заявки необходимо хранить статус заявки со всей историей его изменений. Сразу напрашивается такое решение: хранить статус в другой таблице со всей историей изменений.
| Таблица TStatusHistory | |
| fkey | |
| f_troubleticket | ссылка на запись в TTroubleticket |
| fvalue | значение |
| fsdate | дата присвоения значения |
Тогда чтобы получить текущее значение нам надо выполнить следующий запрос:
SET @f_troubleticket = 10;
SELECT
tt.fkey, tt.fcontact, tt.ftext,
(SELECT
fvalue
FROM
TStatusHistory
WHERE
f_troubleticket = tt.fkey
ORDER BY
fsdate DESC
LIMIT 0,1
) AS fstatus
FROM
TTroubleticket AS tt
WHERE
fkey = @f_troubleticket
LIMIT 0, 1Все складно, все хорошо, ничего лишнего, а при желании мы всегда сможем просмотреть всю историю изменений статуса. Первые трудности начнутся тогда, когда мы попытаемся получить значение на какую-нибудь дату. Поэтому добавим еще одно поле fedate — дата завершения действия значения. Пускай в этом поле будет храниться избыточная информация, но она нам очень
| Таблица TStatusHistory | |
| fkey | |
| f_troubleticket | ссылка на запись в TTroubleticket |
| fvalue | значение |
| fsdate | дата присвоения значения |
| fedate дата | завершения действия значения |
Теперь чтобы получить значение на дату нам надо немного изменить запрос:
SET @f_troubleticket = 10;
SET @dt = 20090401000000; # 01 апреля 2009г 00:00
SELECT
tt.fkey, tt.fcontact, tt.ftext,
(SELECT
fvalue
FROM
TStatusHistory
WHERE
f_troubleticket = tt.fkey
AND @dt BETWEEN fsdate AND fedate
ORDER BY
fsdate DESC
LIMIT 0,1
) as fstatus
FROM
TTroubleticket AS tt
WHERE
fkey = @f_troubleticket
LIMIT 0, 1
С этой сложностью справились. Но время идет, а система совершенствуется: нам понадобился такой параметр как тип заявки и тоже периодический. Фигня!-добавляем еще таблицу.
| Таблица TTypeHistory | |
| fkey | |
| f_troubleticket | ссылка на запись в TTroubleticket |
| fvalue | значение |
| fsdate | дата присвоения значения |
| fedate | дата завершения действия значения |
Зарос преобразуется:
SET @f_troubleticket = 10;
SET @dt = 20090401000000; # 01 апреля 2009г 00:00
SELECT
tt.fkey, tt.fcontact, tt.ftext,
(SELECT
fvalue
FROM
TStatusHistory
WHERE
f_troubleticket = tt.fkey
AND @dt BETWEEN fsdate AND fedate
ORDER BY
fsdate DESC
LIMIT 0,1
) AS fstatus,
(SELECT
fvalue
FROM
TTypeHistory
WHERE
f_troubleticket = tt.fkey
AND @dt BETWEEN fsdate AND fedate
ORDER BY
fsdate DESC
LIMIT 0,1
) AS ftype
FROM
TTroubleticket AS tt
WHERE
fkey = @f_troubleticket
LIMIT 0, 1И со временем у нас может появиться куча дополнительных таблиц, т.е. система усложняется, а в этом нет ничего хорошего.
Усовершенствуем наш подход — не будем создавать отдельные таблицы для каждой периодической переменной, все периодические переменные будем хранить в одной таблице.
| Таблица THistory | |
| fkey | |
| f_troubleticket | ссылка на запись в TTroubleticket |
| fstatus | статус |
| ftype | тип |
| fsdate дата | присвоения значения |
| fedate дата | завершения действия значения |
Также, все актуальные значения будем хранить в основной таблице.
| Таблица TTroubleticket | |
| fkey | номер заявки |
| fcontact | контактная информация подавшего заявку |
| ftext | текст заявки |
| fstatus | текущей статус |
| ftype | текущий тип |
И теперь когда нам понадобится получить актуальные значения, нам достаточно выполнить простой запрос:
SET @f_troubleticket = 10;
SELECT
fkey, fcontact, ftext,
fstatus,
ftype
FROM
TTroubleticket
WHERE
fkey = @f_troubleticket
LIMIT 0, 1Ну, а если нам понадобится получить значения на дату, воспользуемся конструкцией LEFT JOIN:
SET @f_troubleticket = 10;
SET @dt = 20090401000000; # 01 апреля 2009г 00:00
SELECT
tt.fkey, tt.fcontact, tt.ftext,
his.fstatus,
his.ftype
FROM
TTroubleticket AS tt
LEFT JOIN TTroubleticketHistory as his
ON his.f_troubleticket = tt.fkey
AND @dt BETWEEN his.fsdate AND his.fedate
WHERE
tt.fkey = @f_troubleticket
LIMIT 0, 1Вот собственно и всё. Вроде бы получилось очень даже не сложное решение. А как вы храните периодические значения?
p.s. За идею спасибо А. Матвееву.
