2010-03-09 5 views
3

나는 지난 며칠 동안 내 책상에 머리를 대고 있었기 때문에 Stack Overflow를 참조하십시오.매년 MySQL 데이터베이스에 반복 가능한 값 저장

제가 작업하고있는 소프트웨어에는 시간에 민감한 데이터가 있습니다. 이를위한 일반적인 해결책은 효과적이고 만료 날짜입니다.

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

이것은 쉽습니다. 불행히도, 우리는 임의로 먼 미래까지 매년 반복되는 데이터가 필요합니다. 다시 말해, 5 월 1 일부터 2000 년에 이르기까지 유효 가치가 100이되기를 원할 수도 있습니다. 11 월 1 일마다 90으로 변경할 수 있습니다.

이것은 오랜 기간 동안 발생할 수 있습니다 (> 50 년), 그래서 나는 단지 100 개의 레코드를 만들고 싶지 않습니다. 즉,이 작업을 수행하고 싶지 않습니다.

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 년 이전 값 (NO 플립 낫다) 일정되었을 수 있습니다와 향후 10에 대한 값은 마지막의 값과 다를 수 있습니다

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 

2009-11-01이 2009-05-01 이후이므로 오늘의 값은 90 일 것입니다.

에는, 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 

값은 2007-05-01부터 100 나중에 2006-11-01보다 것이다.

MySQL 날짜 함수를 사용하면 MOST_RECENT 필드를 계산하는 가장 효율적인 방법은 무엇입니까?

아니면 누구나 더 좋은 방법을 생각할 수 있습니까?

중요한 언어는 Java입니다. 모두에게 감사드립니다!

답변

2

이 원하는 '날짜를'가정거야 다음의 경우는 false 다음 SQL 쿼리는 90를 반환합니다 '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 one-liner가 처리 할 수없는 (또는 처리해서는 안되는) 많은 지혜가 필요합니다. 도움 주셔서 감사합니다. – Tenner

0

다음은 데이터 세트에 대한 최신 EFF_DT를 계산하는 데 사용할 수있는 쿼리입니다. 이 데이터가 어떻게 구성되어 있는지 확실하지 않기 때문에 where 절을 채워야합니다.

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 월 (5 번째 월)이지만 11 월 (11 번째 월)보다 작은 지 확인합니다. 이것이 사실이라면 당신은 100

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

I을 반복적 인 약속 인 & 이벤트로 비슷한 일을해야했고, MySQL은 원하지 않는 "정적"날짜 스타일로 훨씬 행복해졌습니다. 반복되는 각 인스턴스는 수백 개의 행으로 구성되어 있습니다.

가능한 경우 기존 데이터와 일치하도록 유효 기간/유효 기간을 유지하면서 (균등하게 레거시 데이터 &과 일치하도록) 평탄하게 저장하고 별도의 테이블을 만드는 것이 좋습니다. 두 테이블 (원본 PK를 참조하는 병합 된 데이터의 "event_id"). 모든 기록을 작성하는 데 시간이 더 오래 걸릴 것이지만 읽는 데 걸리는 부담이 직접적으로 줄어 듭니다 (일반적으로 상황이 더 빠를 필요가있는 경우).

일반적인 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

입력 해 주셔서 감사합니다. 데이터를 확장하는 것을 주저하는 이유 중 하나는 이러한 되풀이되는 데이터 포인트를 편집해야 할 수도 있다는 것입니다. 즉, 가치가 90에서 95로 바뀌면 한 곳에서 100으로 바꾸고 싶습니다. 그리고 사용자 인터페이스는이 데이터를 적절한 형식으로 "축소"할 수 있어야합니다. (사용자는 100이 아니라 2 개의 행을보아야합니다.) 여전히 좋은 음식은 여기에 있습니다. – Tenner

관련 문제