주간 데이터 시리즈 간의 트랜잭션을 결정하는 알고리즘은 무엇입니까?


9

sqlite 백엔드가있는 작은보고 도구를 개발하려고합니다. 이 도구를 "거래"원장으로 가장 잘 설명 할 수 있습니다. 내가하려는 것은 주간 데이터 추출에서 "트랜잭션"을 추적하는 것입니다.

  • "신규"(또는 추가)-리소스가 추출을 통해 보이지 않았기 때문에 앱 에서이 리소스를 추적 하지 않았기 때문에 리소스가 내 앱에 새로 추가 되었습니다.
  • "업데이트"(또는 적중)-해당 리소스가 최근에 사용되며 업데이트 보존 기간이 1 주일 더 있습니다.
  • "삭제"(또는 삭제)-이 항목은 마지막 보고서 이후에 사용되지 않았습니다 (선택 사항이지만 자원에 대한 주별 변경 사항을 그래프로 표시하는 것이 좋습니다).

내가 가지고있는 것은 내가 통제 할 수없는 레거시 보관 / 기록 관리 시스템에서 나오는 매주 데이터 추출 (파이프 구분 플랫 파일)입니다.

각 라인은 기본적으로 다음과 같이 증류 될 수 있습니다.
resource_id | resource info | customer_id | customer_info

샘플 데이터 :

10| Title X       | 1 | Bob
11| Another title | 1 | Bob
10| Title X       | 2 | Alice

목표는 X 개월 동안 사용되지 않은 리소스 (마지막 적중을 기준으로)에 대해 쉽게보고 할 수 있도록하는 것입니다. 리소스가 인기있는 경우 쉽게 액세스 할 수 있도록 보존 기간이 유지됩니다. 18 개월 동안 사용되지 않은 리소스는 다른 곳에서 장기 보관이 가능합니다.

이것은 일반적인 문제 여야합니다. 데이터 세트간에 새로운 / 동일한 / 제거 된 것을 결정하는 범용 알고리즘이 있는지 궁금하십니까 (db와 최신 추출)?

답변:


1

네 대답은 ... 네 구현할 수있는 간단한 알고리즘이 있습니다. 다른 알고리즘이 필요하지 않습니다. 순 현재 가치 알고리즘입니다. 구현하기 쉽고 DB 측에서 필요한 것은 주간 데이터에 날짜를 기입하고 간단한 쿼리와 작은 재귀 함수 또는 for 루프를 작성하거나 다른 솔루션 중 하나를 수행 할 수 있다는 것입니다.

NPV = PV- (PV (CP / T) 또는 새로운 현재 가치는 현재 가치와 현재 기간 (마지막 진입 이후의 개월 수)을 자원 값이 0으로 떨어질 때 용어 (예 : 18 개월)로 나눈 현재 가치의 실제 가치와 같습니다. 소비된다.

당신이 나에게 원하는 언어를 주면 여기에 코드를 편집에 게시 할 것입니다.


언어는 그렇게 중요하지 않습니다. 내가 선택해야한다면 루비 또는 C ++. HTML 4.0 Strict에서 알고리즘을 작성할 수 있다면 당신은 나의 영웅이 될 것입니다. 마지막 부분에 대한 이야기 ​​:)
Swartz

코드를보고 싶습니다. 루비 또는 C ++. 감사합니다.
Swartz

0

어쨌든 SQLite 백엔드에 업데이트를 유지하는 경우 매주 업데이트를 새 테이블로 변환하고 병합하기 전에 쿼리를 통해 아카이브 된 데이터와 비교할 수 있습니다.

SQL을 사용하여 테이블에 새로 추가 된 예 : /programming/2077807/sql-query-to-return-differences-between-two-tables

DB의 필드에 거래 날짜가 저장되어 있으면 지난 18 개월 동안 거래를 한 모든 사용자를 쿼리 할 수 ​​있습니다. 그런 다음 아카이브는 전체 DB입니다. 또는 그렇지 않은 모든 사용자를 쿼리하고 데이터를 추출한 다음 삭제할 수 있습니다. 이번 주 업데이트는 타임 스탬프가 지정된 행에 불과합니다.


더 나은, 그것은 적어도 데이터 중심 솔루션은, 그러나 그것은 과잉 여전히
J-보스

시작하기 쉽기 때문에 시간 동안 sqlite를 사용하고 있습니다. MySQL (또는 PostgreSQL)로 쉽게 전환 할 수 있습니다. SQL이 아닌 백엔드를 사용하여이 작업을 더욱 향상시킬 수있는 것이 있다면, 저는 모두 귀합니다.
Swartz

글쎄, 내 생각은 주로 당신이 어쨌든 데이터베이스의 행으로 변환한다고 생각했습니다 . 여러 프로세스에서 동시에 실행할 필요가 없다면 SQLite보다 더 무거운 것으로 전환하고 싶지는 않습니다.
Davislor

동시 처리가 필요 없습니다. 그러나 어딘가에 리소스에 대한 데이터를 저장해야합니다. SQL db는 좋은 선택 인 것처럼 보였지만 델타 처리를 위해 데이터 유형으로 데이터를로드하는 데 방해가되는 것은 없습니다. 각 추출 실행이 끝날 때 원하는 것은 새로운 기능, 무엇이 동일하고 무엇이 사라 졌는지 파악하는 것입니다. 이 정보에서 필요에 따라 레코드를 업데이트하는 방법을 알아낼 수 있습니다.
Swartz

데이터를 파싱하고 데이터베이스에 넣은 후에는 알고리즘을 구현하는 것보다 쿼리를 작성하는 것이 더 간단합니다. 즉, 코딩하려는 경우 원하는 알고리즘은 차이가 있으며 C ++ STL에는 두 데이터 집합을 컨테이너에 넣은 후 한 줄로 수행 할 수있는 구현이 있습니다. 당신의 선택, 아마 Vector.
Davislor

0

대체 아이디어 :

  1. 트랜잭션 목록을 배열과 같은 일종의 데이터 구조로 구문 분석하십시오. (C ++에서는 think Vector및 Java에서는 ArrayList)

  2. SQL 백엔드에서 쿼리를 수행 SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_id하고 정렬 된 개별 고객 ID를 세트로 압축하십시오 old. WHERE이전 트랜잭션과 새 트랜잭션을 구분 하는 절 에서 똑같은 작업을 수행하는 경우 3 단계를 건너 뛸 수 있습니다.

  3. 새로운 업데이트에서 고유 한 고객 ID를 정렬 된 순서로 별도의 데이터 구조로 가져옵니다. 데이터 구조를 얻는 데 사용할 수있는 몇 가지 데이터 구조가 있습니다 new. 이중 연결 목록에 삽입 정렬은 매우 간단하지만 중간 해시 테이블을 사용하면 선형 시간에 가깝게 실행되거나 어쨌든 원래 배열을 정렬하는 경우 쉽게 설정할 수 있습니다.

  4. 집합 차이를 가지고 new- old당신의 마음에 드는 언어의 표준 라이브러리를 사용하여. 가장 좋아하는 언어는이 알고리즘을 표준 라이브러리에 있습니까?

트랜잭션 데이터베이스를 업데이트 한 후에도 SQL 쿼리를 수행해야합니다.

3 단계에 대한 참고 사항 : 데이터의 특성을 고려하십시오. 텍스트 파일에 시간 순서대로 주문이 나열되고 일반적으로 1 주일에 새로운 고객이 customer_id오름차순으로 주문 된다고 가정합니다 . 대부분의 다른 주문이 적은 수의 충실한 반복 고객으로부터 이루어지고 있다고 가정합시다 customer_id. 그런 다음 입력 내용이 이미 정렬되어 있습니다. customer_id이중 연결 목록의 앞쪽에 low를 삽입 customer_id하고 뒤쪽에 high 를 삽입하는 삽입 정렬 은 실제로는 성능이 우수 합니다.


1
고객보다는 새로운 / 동일한 / 업데이트 된 리소스 에 더 관심 이 있습니다. 그러나 예, 아이디어는 동일합니다.
Swartz

0

귀하의 질문에서 알 수 있듯이 실제로 resource_id (+ info) 및 고객 (id + info)의 "목록"이 있습니다.

따라서 리소스 당 고객 목록을 쉽게 유지하고 리소스의 각 목록에서 마지막 노드를 확인할 수 있습니다 (마지막 작업 시간을 알기 위해 코드에서 고객에게 날짜 필드를 추가하면 됨)

SQL에 익숙하지 않으므로 예와 HashMapList 를 사용 하여 예제를 제공 하지만 resourceID를 키로 포함하고 고객 ID, 정보 및 작업 날짜를 포함 해야하는 HashMap <Resource, List<Customer>>경우 와 동일한 아이디어 입니다.ResourceCustomer

이 아이디어를 사용하면 마지막 작업 시간을 쉽게 알 수 있으며 모든 자원을 수정할 수 있습니다 (자원 추가 / 제거 \ 고객).


0

SqLite 데이터베이스를 사용하는 경우 배치 날짜를 테이블 열로 추가하면,

10| Title X       | 1 | Bob    | 2015-03-01
11| Another title | 1 | Bob    | 2015-03-01
...............................
10| Title X       | 1 | Alice  | 2015-03-05

지난 X 일 동안 사용되지 않은 리소스를 얻기 위해 SQL을 사용하는 것은 매우 쉽습니다.

Select distinct r.ResourceID from Resources r
where not exists (SELECT julianday('now') - julianday(r.DateUpdated)) < X

SQL을 테스트하지는 않았지만 아이디어를 제공해야합니다.


0

원래 게시물에서 수집 된 데이터에 거래 날짜 / 시간을 나타내는 필드가없는 것처럼 들리며 매일, 시간 등의 일정에 따라 파일이 자주 수집된다고 가정합니다.

데이터베이스 수준에서 자동 생성되거나 데이터를 추출하고 DB에 삽입하는 코드로 SQL 타임 스탬프 열을 추가하여이를 처리합니다. 그런 다음 해당 시간 소인 열에 색인을 작성하고 완료하십시오. DB 엔진이 "이 시점 이후로 발생한 트랜잭션 수"또는 "이 시간과 그 시간 사이에 발생한 트랜잭션 수"에 대한 질문에 효율적으로 응답하도록하십시오.

그런 다음보고 할 차이를 쿼리하고 계산할 작업을 예약합니다. "신규"트랜잭션은 "신규 이후"를 요청한 날짜 이전에 DB에 레코드가없는 트랜잭션입니다. 오래된 레코드는 마감일 이후 거래가없는 레코드입니다.


-2

이것이 HashTables에 대한 것이 아닙니까? 지난 몇 달 동안 사용한 리소스에 대한 기록을 유지하고 지난 18 개월 동안 액세스하지 않은 리소스를 삭제하기 만하면 키가 resource_id이고 값이 마지막 액세스 날짜.

> 18 개월 레코드를 아카이브하기 위해 해시 테이블의 모든 레코드를 살펴보고 해당 특정 레코드를 제거 (또는 이동) 할 수 있습니다. (보고서가 올 때마다 매주 할 수 있습니다)


데이터베이스에 물건을 저장하는 경우 HashTable이 필요한 이유는 무엇입니까? DB 레코드를 업데이트 할 수 있습니다. 더 관심이있는 경우 : 두 개의 데이터 세트를 가져 와서 두 세트의 차이점 (추가 된 내용, 동일하게 유지됨, 삭제됨)을 찾으십시오. HashTable 기술이 새로운 "제거 된"레코드를 찾는 데 어떻게 도움이됩니까?
Swartz

테이블이 데이터베이스에서 인덱스되면 기본적으로 HashTables입니다. 각각 데이터 세트를 나타내는 2 개의 테이블이있는 경우 외부 조인을 수행하여 새 레코드와 제거 된 레코드를 얻을 수 있습니다. i.stack.imgur.com/pxUO3.png 참조하십시오 . resource_id 열에 인덱스가 있는지 확인하고 매우 빠릅니다. 이것을 처음부터 구현해야한다면 O (1) 할부 상환 시간에 조회 / 삽입 / 삭제를 수행 할 수 있으므로 HashTables가 여전히 갈 길이라고 생각합니다. 더 효율적인 방법을 생각할 수 없습니다.
Adrian Buzea

3
해시 테이블에 추가하는 단계없이 노화를 처리하는 더 나은 데이터 구조가 있습니다.

몇 가지 언급 하시겠습니까?
Adrian Buzea

@Snowman - 내가 몇 번, 난 그냥 단호이이 의견에 동의거야 속도 최대 수 소원
J-보스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.