Алгоритм визначення транзакцій серед тижневих рядів даних?


9

Я намагаюся розробити невеликий засіб звітування (із бекендом sqlite). Я найкраще можу описати цей інструмент як "транзакційну" книгу. Що я намагаюся зробити - це відслідковувати "транзакції" з виписки даних щотижня:

  • "new" (або додати) - ресурс є новим для мого додатка, оскільки мій додаток, можливо, не відстежував цей ресурс раніше, оскільки його не бачили за допомогою виписок.
  • "оновлення" (або звернення) - нещодавно використовується цей ресурс, оновлення періоду зберігання ще на тиждень.
  • "delete" (або "drop") - цей елемент не використовувався з останнього звіту (необов'язково, але було б непогано мати графік змін попиту на ресурси на тиждень).

Все, що у мене є, - це щотижневий витяг даних (плоский файл з обмеженими каналами), що надходить із застарілої системи архівування / управління записом, над якою я не маю ніякого контролю.

Кожен рядок можна перегнати таким чином:
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 vs. останній витяг)?

Відповіді:


1

Ну і ваша відповідь ... Так. Існує простий алгоритм, який ви можете реалізувати, який не вимагає жодного іншого. Це алгоритм чистого теперішнього значення. Це легко здійснити, і все, що потрібно для кінця БД, полягає в тому, що ви датуєте штампування даних про тиждень і пишете один простий запит і одну невелику рекурсивну функцію або для циклу, або ви можете зробити одне з цих інших рішень.

NPV = PV- (PV (CP / T) або Нове теперішнє значення дорівнює теперішньому значенню в рази на поточний період (місяці з моменту останнього запису), поділене на термін (наприклад, 18 місяців), коли значення ресурсу падає на 0 - це чисте теперішнє значення витрачається.

Якщо ви дасте мені язик, який ви хочете в ньому, я опублікую код тут у редакції


Мова не так важлива. Ruby або C ++, якщо мені доведеться вибирати. Якщо ви зможете написати алгоритм в HTML 4.0 Strict, ви будете моїм героєм. Жартую про цю останню частину :)
Swartz

Буде зацікавлено переглянути код. Ruby або C ++. Дякую.
Шварц

0

Якщо ви все одно зберігаєте оновлення в серверній програмі SQLite, ви можете перетворити щотижневе оновлення в нову таблицю і порівняти їх із заархівованими даними із запитами, перш ніж об'єднати їх.

Приклад використання SQL для пошуку нових доповнень до таблиці: /programming/2077807/sql-query-to-return-differences-between-two-tables

Якщо в полі вашої БД зберігається дата трансакції, ви можете просто запитувати всіх користувачів, які мали операції за останні 18 місяців. Тоді архів - це лише повна БД. Крім того, ви можете запитувати всіх користувачів, які цього не зробили, витягнути їхні дані та видалити їх. Оновлення - це будь-які рядки, розмічені на цьому тижні.


Краще, це рішення, орієнтоване на дані, принаймні, але це все-таки надмірно
J-Boss

Я зараз використовую sqlite, як це легко почати. Легко перейти на MySQL (або PostgreSQL). Якщо використання бекенда no-SQL буде нічого, щоб зробити цю роботу ще кращою, я все вухо.
Swartz

Ну, в основному я думав, що ти все одно перетворюєш їх у рядки в базі даних . Якщо вам не потрібно одночасно запускати його з декількох процесів, я не думаю, що ви хочете перейти на щось більш важке, ніж SQLite.
Девіслор

Немає необхідності в одночасній обробці. Але мені потрібно десь зберігати дані про ресурси. SQL db здався гарним вибором, однак, ніщо не заважає мені завантажувати дані в будь-який тип даних для обробки дельт. Все, що я хочу в кінці кожного витягу, - це з’ясувати, що нового, що залишилось тим самим і що зникло. Я можу зрозуміти, як оновлювати записи за необхідності з цієї інформації.
Swartz

Після того як ви проаналізували дані та помістили їх у базу даних, можливо, простіше написати запит, ніж реалізувати алгоритм. Це означає, що якщо ви хочете його кодувати, алгоритм, який ви хочете, - це різниця в налаштуваннях, і в C ++ STL є реалізація, яку ви можете використовувати для цього в одному рядку, як тільки ви вставите обидва набору даних у контейнер ваш вибір, ймовірно, a Vector.
Девіслор

0

Альтернативна ідея:

  1. Розбирайте свій список транзакцій на якусь структуру даних, наприклад, масив. (В C ++, думай Vector, і в Java,. ArrayList)

  2. Виконайте запит на вашому SQL бакенд , такий як SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_idі пакет відсортованої різних ідентифікаторів клієнтів в набір, old. Якщо ви робите саме те саме з WHEREпунктом, що розділяє стару та нову транзакції, ви можете пропустити крок 3.

  3. Отримайте унікальні ідентифікатори клієнтів з нових оновлень в окрему структуру даних, впорядкованому порядку. Є кілька структур даних , які ви можете використовувати , щоб отримати це в структуру даних, new. Сортування вставки у подвійний зв'язаний список дуже простий, але використання проміжного хештелю запуститься близько до лінійного часу, або якщо ви все одно сортуєте оригінальний масив, отримати набір із цього просто.

  4. Візьміть різницю в наборі new- oldвикористовуючи стандартну бібліотеку улюбленої мови. Ця улюблена мова має цей алгоритм у своїй стандартній бібліотеці?

Інші речі, які ви хочете зробити, - це безперечно запити SQL після оновлення бази даних транзакцій.

Примітка до кроку 3: Розгляньте характер ваших даних. Припустимо, що ваш текстовий файл перераховує замовлення хронологічно, а типовий тиждень є багато клієнтів-початківців, яким надається новий customer_idу порядку зростання. Припустимо, що більшість інших замовлень - від невеликої кількості відданих клієнтів, які повторюються, з меншими customer_id. Тоді ваші входи вже в основному відсортовані. Сортування вставки, де ви намагаєтеся вставити внизу внизу customer_idсписку з подвійним зв’язком і високо внизу customer_id, в цій ситуації буде добре на практиці.


1
Мене більше цікавлять нові / ті самі / оновлені ресурси, а не клієнти. Але так, ідея була б такою ж.
Swartz

0

Як я розумію з вашого запитання, ви насправді маєте resource_id (+ info) та "список" клієнта (id + info).

Таким чином, ви можете легко зберігати Список клієнтів на ресурс і перевіряти останній вузол у кожному списку ресурсу (для того, щоб знати час останньої операції; потрібно просто додати поле коду до свого клієнта у код)

Я не знайомий з SQL, тому я наводжу свій приклад з HashMapі Список, але я впевнений, що це одна і та ж ідея:, HashMap <Resource, List<Customer>>коли Resourceповинен містити resourceID як ключ і Customerповинен містити ідентифікатор клієнта, інформацію та дату роботи.

За допомогою цієї ідеї ви можете легко знати час останньої роботи та можете змінювати будь-який ресурс (додати \ видалити ресурс \ клієнта).


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

досить просто використовувати SQL, щоб отримати ресурси, які не використовувались протягом останніх X числа днів

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

Я не перевіряв SQL, але він повинен дати вам уявлення


0

З оригінальної публікації звучить так, що в даних, що приймаються, немає поля для вказівки дати / часу трансакції, і я припускаю, що файл приймається часто, за графіком, наприклад, щодня, щогодини тощо.

Я б вирішив це, додавши стовпець часової мітки SQL, який або автоматично генерується на рівні бази даних, або кодом, який витягує дані та вставляє в БД. Потім ви ставите індекс на цей стовпець часової позначки і виконайте його. Нехай двигун БД зробить ефективну відповідь на питання "скільки транзакцій не відбулося за цей час" або "скільки між цим часом і тим часом".

Тоді ви плануєте роботу для запиту та обчислення різниць, про які потрібно звітувати. "Нові" транзакції - це транзакції, які не мають записів у БД до дати, про яку ви запитуєте "нові з моменту". Старі записи - це ті, які не мають транзакцій з моменту закінчення.


-2

Це не те, для чого призначені HashTables? Якщо все, що ви хочете зробити, це зберегти записи про те, які ресурси використовувались протягом останніх місяців, і видалити ресурси, до яких не зверталися протягом останніх 18 місяців, тоді ви можете використовувати HashTable, де ключ - Resource_id, а значення - остання дата доступу.

Для архівації записів> 18 місяців ви можете пройти всі записи в хеш-таблиці та просто видалити (або перемістити) ці конкретні записи. (це можна робити щотижня, коли надходить звіт)


Чому потрібна HashTable, якщо я зберігаю речі в базі даних? Я можу робити оновлення для db-записів. Мене більше цікавить випадок: візьміть два набори даних, з’ясуйте відмінності (те, що додано, залишається незмінним, видалено) між двома наборами. Як би допомогла методика HashTable у пошуку нових та "вилучених" записів?
Шварц

Якщо таблиці індексуються в базі даних, вони в основному також є HashTables за кадром. Якщо у вас є дві таблиці, кожна з яких представляє набір даних, ви можете отримати свої нові та вилучені записи, виконавши деякі зовнішні з'єднання. Дивіться це для довідки: i.stack.imgur.com/pxUO3.png . Переконайтеся, що у вас є індекси в колонці resource_id, і це має бути досить швидким. Якби вам довелося реалізувати це з нуля, я думаю, що HashTables все-таки буде шляхом, оскільки ви можете зробити пошук / вставлення / видалення за амортизованим часом O (1). Не можете придумати більш ефективний спосіб зробити це.
Адріан Бузеа

3
Існують кращі структури даних, які вирішують процес старіння без зайвих кроків введення цього в хеш-таблицю.

Хочете згадати деякі?
Адріан Бузеа

@Snowman - Я хотів би, щоб я зміг оцінити, що ще кілька разів, я просто наголошу в цьому коментарі
J-Boss
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.