2010-03-09 2 views
3

Я уже несколько дней стуча головой о стол, и поэтому я обращаюсь к вам, переполнение стека.Сохранение повторяющихся значений в базе данных MySQL

Программное обеспечение, над которым я работаю, имеет чувствительные к времени данные. Обычное решение для этого является эффективным и сроком действия.

EFF_DT  XPIR_DT  VALUE 
2000-05-01 2000-10-31 100 
2000-11-01 (null)  90 

Это было бы легко. К сожалению, нам требуются данные, которые повторяются на ежегодной основе произвольно далеко в будущее. Другими словами, каждый 1 мая (начиная с 2000 года) нам может потребоваться, чтобы эффективная стоимость составляла 100, и каждый 1 ноября мы можем изменить ее на 90.

Это может случиться в течение длительного времени (> 50 лет), и поэтому я не хочу просто создавать сто записей. I.e., я не хочу этого делать:

EFF_DT  XPIR_DT  VALUE 
2000-05-01 2000-10-31 100 
2000-11-01 2001-04-30 90 
2001-05-01 2001-10-31 100 
2001-11-01 2002-04-30 90 
2002-05-01 2002-10-31 100 
2002-11-01 2003-04-30 90 
... 
2049-05-01 2049-10-31 100 
2049-11-01 2050-04-30 90 
2050-05-01 2050-10-31 100 
2050-11-01 2051-04-30 90 

Эти значения также могут меняться со временем. Значения до 2000 года могут быть постоянными (не флип-флоп) и значение в ближайшем десятилетии может отличаться от значений для последнего:

EFF_DT  XPIR_DT  REPEATABLE VALUE 
1995-01-01 2000-04-30 false  85 
2000-05-01 2010-04-30 true  100 
2000-11-01 2010-10-31 true  90 
2010-05-01 (null)  true  120 
2010-11-01 (null)  true  115 

У нас уже есть текстовый файл (от унаследованного приложения), который хранит данные в форме, очень близкой к этому, поэтому есть преимущества для максимально приближенного к этому типу структуры.

Вопрос тогда приходит к поиску: какое значение применимо к сегодняшнему дню, 2010-03-09?

Кажется, что лучший способ сделать это - найти самый последний экземпляр каждой эффективной даты (всех активных строк), а затем посмотреть, какая из них самая большая.

EFF_DT  MOST_RECENT XPIR_DT  VALUE 
2000-05-01 2009-05-01 2010-04-30 100 
2000-11-01 2009-11-01 2010-10-31 90 

Стоимость на сегодня будет 90, с 2009-11-01 позже 2009-05-01.

, скажем, 2007-06-20:

EFF_DT  MOST_RECENT XPIR_DT  VALUE 
2000-05-01 2007-05-01 2010-04-30 100 
2000-11-01 2006-11-01 2010-10-31 90 

значение будет 100, так как 2007-05-01 позднее, чем 2006-11-01.

Использование функций даты MySQL, что является наиболее эффективным способом расчета поля MOST_RECENT?

Или, может ли кто-нибудь подумать о лучшем способе сделать это?

Язык Java, если это имеет значение. Спасибо всем!

ответ

2

Пусть ваш хотел «дата» является «2007-06-20».

Вы должны объединить неповторяющиеся элементы с повторяющимися из них, так что вы могли бы сделать что-то вроде этого (непроверенное и, возможно, нуждается в некотором thinkering, но должны дать вам общее представление):

select * from (
    select * from mytable 
    where 
    repeatable = false 
    and 
    EFF_DT <= '2007-06-20' < XPIR_DT 
    union all 
    select * from mytable 
    where 
    repeatable = true 
    and EFF_DT <= str_to_date(concat("2007", "-", month(EFF_DT), "-", day(EFF_DT)), "%Y-%m-%d") < XPIR_DT 
) 
order by EFF_DT desc limit 1 
+0

Спасибо ... Я положу в некоторых тестовых данных и дать этому выстрел. Я дам вам знать, как это получается. :-) – Tenner

+0

Я надеялся сделать это в одном хите базы данных - получить все данные, при этом база данных снабдит мой код Java «подсказкой» о том, какую строку использовать. Я думаю, что я собираюсь представить всю вашу логику в базовом коде Java. Есть много умений, которые мне нужно включить в то, что однострочный интерфейс MySQL просто не может (или не должен) обрабатывать. Спасибо за помощь! – Tenner

0

Вот запрос, который вы можете использовать для расчета более позднего EFF_DT для набора данных. Вы должны будете заполнить там, где предложение, потому что я не уверен, как эти данные организованы.

select EFF_DT form date_table where 1 order by EFF_DT desc limit 1 

Флип Флоп 90 и 100 является более сложным, но вы должны быть в состоянии позаботиться об этом с помощью mysql data and time functions. Это сложный вопрос, и я не на 100% на то, что вы пытаетесь сделать. Но этот запрос проверяет, превышает ли месяц XPIR_DT май (5-й месяц), но меньше ноября (11-й месяц). Если это верно, то запрос SQL возвратит 90, если его ложь, то вы получите 100.

select if((month(XPIR_DT)>=5) and (month(XPIR_DT)<11),90,100) from date_table where id=1 
1

I «Мне приходилось делать подобные вещи с повторяющимися встречами событий &, и вы могли бы обнаружить, что MySQL будет намного счастливее с« статическим »стилем даты, который вам не нужен, - каждый повторяющийся экземпляр изложено в сотнях строк.

Если возможно, я бы подумал о создании отдельной таблицы, чтобы сохранить их сглаженные, сохраняя даты действенных/истекающих сроков, где они находятся (для сопоставления устаревших данных & действуют как родительские) и соотношение 1: две таблицы (т.е. «event_id» на сплющенных данных, ссылающихся на PK оригинала). Написание всех этих записей, очевидно, займет больше времени, но это напрямую облегчает загрузку от их чтения (где вещи обычно должны быть быстрее).

Создание хранимой процедуры или внешней программы для обработки пересчета плоской таблицы start_date/end_date/value должно быть довольно простым, учитывая общий интервал. Запрос данных может быть таким же простым, как WHERE @somedate BETWEEN start_date AND end_date, а не все более сложные преобразования & математика дата.

Опять же, INSERT и UPDATE будут медленнее, но «сотни строк» ​​даже не царапают поверхность того, на что способен MySQL. Если это всего лишь 2 даты, int и некоторый тип ключа int, написание нескольких сотен записей не должно занимать пару секунд на субпараллельном сервере. Если бы мы говорили миллионы записей, возможно, что-то можно было бы изменить (действительно ли вам нужно отслеживать 50 лет вперед или только следующие 5? Можно ли перерасчет переместить в нерабочее время через cron? И т. Д.), Но даже тогда MySQL будет просто быть намного эффективнее по сравнению с вычислением разницы каждый раз.

Также может быть интересно: What's the best way to model recurring events in a calendar application? & Data structure for storing recurring events?

+0

Спасибо за ваш вклад. Одной из причин, по которым я не решаюсь расширить данные, является то, что может потребоваться отредактировать эти повторяющиеся точки данных. I.e., если значение изменяется от 90 до 95, я бы хотел изменить его в одном месте, а не сто. И пользовательский интерфейс должен иметь возможность «сворачивать» эти данные до разумной формы. (Пользователь должен увидеть две строки, а не 100.) Тем не менее, хорошая пища для размышлений здесь ... – Tenner

Смежные вопросы