Thuật toán xác định giao dịch giữa các chuỗi dữ liệu hàng tuần?


9

Tôi đang cố gắng phát triển một công cụ báo cáo nhỏ (với phụ trợ sqlite). Tôi có thể mô tả tốt nhất công cụ này như một sổ cái "giao dịch". Những gì tôi đang cố gắng làm là theo dõi "giao dịch" từ trích xuất dữ liệu hàng tuần:

  • "mới" (hoặc thêm) - tài nguyên là mới đối với ứng dụng của tôi vì ứng dụng của tôi có thể chưa theo dõi tài nguyên này trước đây vì nó chưa được nhìn thấy qua các trích xuất.
  • "Cập nhật" (hoặc nhấn) - có một lần sử dụng tài nguyên đó gần đây, thời gian lưu giữ cập nhật thêm một tuần nữa.
  • "xóa" (hoặc bỏ) - mục này không được sử dụng kể từ báo cáo cuối cùng (tùy chọn, nhưng sẽ rất tuyệt nếu có biểu đồ thay đổi theo tuần theo nhu cầu về tài nguyên).

Tất cả những gì tôi có là một trích xuất dữ liệu hàng tuần (tệp phẳng được phân định bằng đường ống) đến từ hệ thống lưu trữ / quản lý hồ sơ cũ mà tôi không kiểm soát được.

Mỗi dòng có thể được chưng cất về cơ bản này:
resource_id | resource info | customer_id | customer_info

Dữ liệu mẫu:

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

Mục tiêu là làm cho nó dễ dàng báo cáo về các tài nguyên chưa từng thấy sử dụng trong X tháng (dựa trên lần truy cập cuối cùng). Có một giai đoạn duy trì nơi các tài nguyên được giữ xung quanh để dễ truy cập nếu chúng phổ biến. Một tài nguyên đã không thấy sử dụng trong 18 tháng được đánh dấu để lưu trữ lâu dài ở nơi khác.

Đây phải là một vấn đề phổ biến. Tự hỏi nếu có một thuật toán có mục đích chung để xác định những gì mới / giống / bị xóa giữa các tập dữ liệu (db so với trích xuất mới nhất)?

Câu trả lời:


1

Vâng, câu trả lời của bạn là ... Vâng. Có một thuật toán đơn giản mà bạn có thể thực hiện mà không yêu cầu bất kỳ thứ gì khác. Đó là một thuật toán giá trị hiện tại ròng. Thật dễ dàng để thực hiện và tất cả những gì nó yêu cầu ở đầu DB là bạn đóng dấu dữ liệu hàng tuần và viết một truy vấn đơn giản và một hàm đệ quy nhỏ hoặc cho vòng lặp, hoặc bạn có thể thực hiện một trong những giải pháp khác.

NPV = PV- (PV (CP / T) hoặc Giá trị hiện tại mới bằng với Giá trị hiện tại nhân với Thời kỳ hiện tại (tháng kể từ lần nhập cuối cùng) chia cho Thời hạn (ví dụ: 18 tháng) khi giá trị tài nguyên giảm xuống 0 được sử dụng

Nếu bạn cho tôi một lang bạn muốn nó, tôi sẽ đăng mã ở đây trong một chỉnh sửa


Ngôn ngữ không quan trọng. Ruby hoặc C ++ nếu tôi phải chọn. Nếu bạn có thể viết một thuật toán trong HTML 4.0 Strict, bạn sẽ là người hùng của tôi. Đùa về phần cuối cùng đó :)
Swartz

Sẽ được quan tâm để xem mã. Ruby hoặc C ++. Cảm ơn bạn.
Swartz

0

Nếu bạn vẫn giữ các bản cập nhật trong phần phụ trợ SQLite, bạn có thể biến bản cập nhật hàng tuần thành một bảng mới và so sánh nó với dữ liệu lưu trữ với các truy vấn, trước khi hợp nhất nó.

Ví dụ về việc sử dụng SQL để tìm các bổ sung mới vào bảng: /programming/2077807/sql-query-to-return-differences-b between-two-tests

Nếu một trường trong DB của bạn lưu trữ ngày giao dịch, bạn có thể truy vấn tất cả người dùng đã có giao dịch trong 18 tháng qua. Sau đó, kho lưu trữ chỉ là DB đầy đủ. Ngoài ra, bạn có thể truy vấn tất cả người dùng chưa có, trích xuất dữ liệu của họ, sau đó thả chúng. Các bản cập nhật chỉ là bất kỳ hàng nào được đánh dấu thời gian trong tuần này.


Tốt hơn, đó là một giải pháp tập trung vào dữ liệu ít nhất, nhưng nó vẫn quá mức cần thiết
J-Boss

Tôi đang sử dụng một sqlite trong thời gian này vì nó dễ dàng để bắt đầu. Có thể dễ dàng chuyển sang MySQL (hoặc PostgreSQL). Nếu sử dụng một phụ trợ không có SQL sẽ tạo ra bất cứ điều gì để làm cho công việc này trở nên tốt hơn nữa, tôi sẽ nghe được.
Swartz

Vâng, suy nghĩ của tôi là chủ yếu mà bạn đang chuyển đổi nó để hàng trong một cơ sở dữ liệu nào . Nếu bạn không cần phải chạy nó từ nhiều tiến trình đồng thời, tôi không nghĩ bạn muốn chuyển sang một thứ gì đó nặng hơn SQLite.
Davislor

Không cần xử lý đồng thời. Nhưng tôi cần lưu trữ dữ liệu về tài nguyên ở đâu đó. Một db SQL có vẻ như là một lựa chọn tốt, tuy nhiên, không có gì ngăn cản tôi tải dữ liệu vào bất kỳ kiểu dữ liệu nào để xử lý deltas. Tất cả những gì tôi muốn ở cuối mỗi lần trích xuất là tìm ra cái gì mới, cái gì vẫn giữ nguyên và cái gì đã biến mất. Tôi có thể tìm ra cách cập nhật hồ sơ khi cần thiết từ thông tin này.
Swartz

Sau khi bạn phân tích dữ liệu và đưa dữ liệu vào cơ sở dữ liệu, việc viết truy vấn có thể đơn giản hơn so với thực hiện thuật toán. Điều đó nói rằng, nếu bạn muốn mã hóa nó, thuật toán bạn muốn được đặt khác biệt và có một triển khai trong C ++ STL mà bạn có thể sử dụng để thực hiện nó trong một dòng duy nhất khi bạn đặt cả hai bộ dữ liệu vào bộ chứa sự lựa chọn của bạn, có lẽ là a Vector.
Davislor

0

Ý tưởng thay thế:

  1. Phân tích danh sách các giao dịch của bạn thành một số loại cấu trúc dữ liệu, chẳng hạn như một mảng. (Trong C ++, hãy suy nghĩ Vectorvà trong Java , ArrayList.)

  2. Thực hiện truy vấn trên phụ trợ SQL của bạn, chẳng hạn như SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_idvà đóng gói ID khách hàng riêng biệt được sắp xếp vào một bộ , old. Nếu bạn thực hiện chính xác điều tương tự với một WHEREđiều khoản phân tách các giao dịch cũ và mới, bạn có thể bỏ qua bước 3.

  3. Nhận ID khách hàng duy nhất từ ​​các bản cập nhật mới vào một cấu trúc dữ liệu riêng biệt, theo thứ tự được sắp xếp. Có một vài cấu trúc dữ liệu bạn có thể sử dụng để có được cấu trúc dữ liệu new. Việc sắp xếp chèn vào danh sách liên kết đôi rất đơn giản, nhưng sử dụng hàm băm trung gian sẽ chạy gần với thời gian tuyến tính hoặc nếu bạn sắp xếp mảng gốc bằng mọi cách, việc lấy ra một cách dễ dàng.

  4. Lấy sự khác biệt đã đặt new- oldsử dụng thư viện chuẩn của ngôn ngữ yêu thích của bạn. Ngôn ngữ yêu thích của bạn có thuật toán này trong thư viện tiêu chuẩn của nó?

Những thứ khác bạn muốn làm chắc chắn là các truy vấn SQL sau khi bạn đã cập nhật cơ sở dữ liệu giao dịch của mình.

Lưu ý ở bước 3: Xem xét bản chất của dữ liệu của bạn. Giả sử rằng tệp văn bản của bạn liệt kê các đơn đặt hàng theo thứ tự thời gian và trong một tuần thông thường, có rất nhiều khách hàng lần đầu tiên được cung cấp một customer_idthứ tự mới theo thứ tự tăng dần. Giả sử rằng hầu hết các đơn đặt hàng khác là từ một số lượng nhỏ khách hàng trung thành lặp lại, với mức thấp hơn customer_id. Sau đó, đầu vào của bạn đã được sắp xếp chủ yếu. Một loại chèn trong đó bạn cố gắng chèn thấp customer_idở phía trước danh sách liên kết đôi và cao customer_idở phía sau, trong tình huống đó, sẽ hoạt động tốt trong thực tế.


1
Tôi quan tâm nhiều hơn đến các tài nguyên mới / tương tự / được cập nhật hơn là khách hàng. Nhưng vâng, ý tưởng sẽ giống nhau.
Swartz

0

Theo tôi hiểu từ câu hỏi của bạn, bạn thực sự có resource_id (+ thông tin) và "danh sách" khách hàng (id + thông tin).

Vì vậy, bạn có thể dễ dàng giữ Danh sách khách hàng trên mỗi tài nguyên và kiểm tra nút cuối cùng trong mỗi danh sách trên tài nguyên (để biết thời gian hoạt động cuối cùng; bạn chỉ cần thêm trường ngày cho khách hàng của mình trong mã)

Tôi không quen thuộc với SQL, do đó tôi đưa ra ví dụ HashMapvà Danh sách của mình nhưng tôi chắc chắn đó là ý tưởng tương tự: HashMap <Resource, List<Customer>>khi nào Resourcenên chứa resourceID làm khóa và Customernên chứa ID khách hàng, thông tin và ngày hoạt động.

Với ý tưởng này, bạn có thể dễ dàng biết được thời gian hoạt động vừa qua và có thể sửa đổi bất kỳ tài nguyên nào (thêm \ remove resource \ customer).


0

Nếu bạn đang sử dụng cơ sở dữ liệu SqLite, nếu bạn thêm ngày của lô cũng như một cột của bảng,

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

sử dụng SQL khá dễ dàng để lấy các tài nguyên không được sử dụng trong số ngày X cuối cùng

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

Tôi chưa kiểm tra SQL nhưng nó sẽ cho bạn một ý tưởng


0

Từ bài đăng gốc, có vẻ như dữ liệu được nhập vào không có trường để chỉ ra ngày / giờ của giao dịch và tôi cho rằng tệp được nhập thường xuyên theo lịch như hàng ngày, hàng giờ, v.v.

Tôi sẽ xử lý việc này bằng cách thêm một cột dấu thời gian SQL, được tự động tạo ở cấp cơ sở dữ liệu hoặc bằng mã trích xuất dữ liệu và chèn vào DB. Sau đó, bạn đặt một chỉ mục trên cột dấu thời gian đó và được thực hiện với nó. Hãy để công cụ DB thực hiện công việc làm cho nó hiệu quả để trả lời câu hỏi "có bao nhiêu giao dịch đã xảy ra kể từ thời điểm này" hoặc "có bao nhiêu giữa thời gian này và thời điểm đó".

Sau đó, bạn lên lịch một công việc để truy vấn và tính toán các khác biệt mà bạn muốn báo cáo. Giao dịch "mới" là các giao dịch không có bất kỳ hồ sơ nào trong DB trước ngày bạn yêu cầu "mới kể từ". Hồ sơ cũ là những hồ sơ không có giao dịch kể từ ngày giới hạn.


-2

Đây không phải là những gì HashTables dành cho? Nếu tất cả những gì bạn muốn làm là giữ các bản ghi về những tài nguyên đã được sử dụng trong những tháng qua và xóa các tài nguyên không được truy cập trong 18 tháng qua thì bạn có thể sử dụng HashTable trong đó Khóa là resource_id và giá trị là ngày truy cập cuối cùng.

Để lưu trữ các bản ghi> 18 tháng, bạn có thể đi qua tất cả các bản ghi trong bảng băm và chỉ cần xóa (hoặc di chuyển) các bản ghi cụ thể đó. (bạn có thể làm điều này hàng tuần khi báo cáo đến)


Tại sao cần HashTable nếu tôi đang lưu trữ nội dung trong cơ sở dữ liệu? Tôi có thể cập nhật các bản ghi db. Tôi quan tâm nhiều hơn đến một trường hợp: lấy hai bộ dữ liệu, tìm ra sự khác biệt (những gì được thêm vào, vẫn giữ nguyên, bị xóa) giữa hai bộ. Kỹ thuật HashTable sẽ hỗ trợ tìm kiếm các bản ghi mới và "loại bỏ" như thế nào?
Swartz

Nếu các bảng được lập chỉ mục trong cơ sở dữ liệu thì về cơ bản chúng cũng là HashTables đằng sau hậu trường. Nếu bạn có 2 bảng, mỗi bảng biểu thị một tập dữ liệu thì bạn có thể lấy các bản ghi mới và loại bỏ bằng cách thực hiện một số phép nối ngoài. Xem phần này để tham khảo: i.stack.imgur.com/pxUO3.png . Hãy chắc chắn rằng bạn có các chỉ mục trên cột resource_id và nó sẽ khá nhanh. Nếu bạn phải thực hiện điều này từ đầu thì tôi nghĩ HashTables vẫn sẽ là cách để bạn có thể thực hiện tra cứu / chèn / xóa trong thời gian khấu hao O (1). Không thể nghĩ ra một cách hiệu quả hơn để làm điều này.
Adrian Buzea

3
Có các cấu trúc dữ liệu tốt hơn để xử lý lão hóa mà không cần thêm các bước nhồi nhét này vào bảng băm.

Quan tâm để đề cập đến một số?
Adrian Buzea

@Snowman - Tôi ước tôi có thể tăng giá thêm vài lần nữa, tôi sẽ hoàn toàn đồng ý trong nhận xét này
J-Boss
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.