Haftalık veri serileri arasındaki işlemleri belirlemek için algoritma?


9

Küçük bir raporlama aracı (sqlite arka uç ile) geliştirmeye çalışıyorum. Bu aracı en iyi "işlem" defteri olarak tanımlayabilirim. Ne yapmaya çalışıyorum haftalık veri ayıklamak "işlemleri" takip etmektir:

  • "yeni" (veya ekleme) - benim app olabileceğinden kaynak Uygulamama yenidir değil o özlerinin aracılığıyla görülmedi olarak önce bu kaynağı izlemiş.
  • "güncelleme" (veya isabet) - bu kaynağın yakın zamanda kullanımı var, saklama süresini bir hafta daha güncelleyin.
  • "sil" (veya bırak) - bu öğe son rapordan bu yana bir işe yaramadı (isteğe bağlı, ancak kaynak talebinde haftadan haftaya değişikliklerin grafiğini almak için iyi olurdu).

Elimdeki tek şey, üzerinde hiçbir kontrole sahip olmadığım eski bir arşivleme / kayıt yönetimi sisteminden gelen haftalık bir veri özütüdür (boru ile sınırlandırılmış düz dosya).

Her bir hat temel olarak şu şekilde damıtılabilir:
resource_id | resource info | customer_id | customer_info

Örnek veri:

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

Amaç, X-ay boyunca (son isabet bazında) kullanım görmeyen kaynakları rapor etmeyi kolaylaştırmaktır. Kaynakların, popüler olmaları halinde erişim kolaylığı için etrafta tutulduğu bir saklama süresi vardır. 18 aydır kullanılmayan bir kaynak, başka bir yerde uzun süreli arşivleme için işaretlenmiştir.

Bu yaygın bir sorun olmalı. Veri kümeleri arasında neyin yeni / aynı / neyin kaldırıldığını belirlemek için genel amaçlı bir algoritma olup olmadığını mı merak ediyorsunuz?

Yanıtlar:


1

Cevabınız ... Evet. Uygulayabileceğiniz basit bir algoritma var. Net bir şimdiki değer algoritması. Uygulanması kolaydır ve DB ucunda gereken tek şey, haftalık verileri tarihlendirmeniz ve basit bir sorgu ve bir küçük özyinelemeli işlev veya döngü için yazmanız veya bu diğer çözümlerden birini yapabilmenizdir.

NPV = PV- (PV (CP / T) veya Yeni Mevcut Değer, Kaynak Değer 0'a düştüğünde, Mevcut Dönemin (son girişten bu yana geçen aylar) Dönemin (örneğin 18 ay) bugünkü Değerine eşittir. harcanır.

Bana istediğiniz bir dil verirseniz, kodu burada bir düzenlemeye gönderirim


Dil o kadar önemli değil. Ruby ya da C ++ seçmeliydim. HTML 4.0 Strict'de bir algoritma yazabiliyorsanız kahramanım olacaksınız. O son bölüm hakkında dalga geçiyorum :)
Swartz

Kodu görmek isterim. Ruby veya C ++. Teşekkür ederim.
Swartz

0

Güncellemeleri yine de bir SQLite arka ucunda tutuyorsanız, haftalık güncellemeyi yeni bir tabloya dönüştürebilir ve birleştirmeden önce sorgularla arşivlenen verilerle karşılaştırabilirsiniz.

Bir tabloya yeni eklemeler bulmak için SQL kullanma örneği: /programming/2077807/sql-query-to-return-differences-between-two-tables

DB'nizdeki bir alan işlemin tarihini depolarsa, yalnızca son 18 ay içinde işlem yapmış tüm kullanıcıları sorgulayabilirsiniz. O zaman arşiv sadece tam DB'dir. Alternatif olarak, kullanmayan tüm kullanıcıları sorgulayabilir, verilerini çıkarabilir ve ardından bırakabilirsiniz. Güncellemeler, bu hafta zaman damgasını içeren satırlardır.


Daha da iyisi, en azından veri merkezli bir çözüm, ama yine de aşırı dolu
J-Boss

Başlamak kolay olduğu için bir sqlite kullanıyorum. Kolayca MySQL'e (veya PostgreSQL'e) geçebilir. SQL olmayan bir arka uç kullanmak, bu çalışmayı daha da iyi hale getirmek için her şeyi netleştiriyorsa, tamamen kulaklarım.
Swartz

Eh, benim düşünce bir veritabanında satırlara dönüştürerek konum ağırlıklı olmasıydı zaten . Aynı anda birden çok işlemden çalıştırmanız gerekmiyorsa, SQLite'den daha ağır bir şeye geçmek istediğinizi düşünmüyorum.
Davislor

Eşzamanlı işleme gerek yoktur. Ama kaynaklar hakkındaki verileri bir yerde saklamam gerekiyor. Bir SQL db iyi bir seçim gibi görünüyordu, Ancak, deltaları işlemek için herhangi bir veri türüne veri yüklememi engelleyen bir şey yok. Her bir ekstrakt çalışmasının sonunda istediğim tek şey, neyin yeni olduğunu, neyin aynı kaldığını ve nelerin kaybolduğunu bulmak. Bu bilgilerden gerekli kayıtların nasıl güncelleneceğini anlayabilirim.
Swartz

Verileri ayrıştırıp veritabanına koyduktan sonra, bir sorgu yazmak bir algoritma uygulamaktan daha kolaydır. Bununla birlikte, kodlamak isterseniz, istediğiniz algoritma fark ayarlanır ve C ++ STL'de, her iki veri kümesini kapsayıcıya koyduktan sonra tek bir satırda yapmak için kullanabileceğiniz bir uygulama vardır. seçiminizi, muhtemelen a Vector.
Davislor

0

Alternatif fikir:

  1. İşlem listenizi bir dizi gibi bir tür veri yapısına ayrıştırın. (C ++ ile düşünün Vectorve Java ile ArrayList.)

  2. SQL arka ucunuzda bir sorgu gerçekleştirin SELECT DISTINCT customer_id FROM Transactions ORDER BY customer_idve sıralanan farklı müşteri kimliklerini bir kümeye paketleyin old. Aynı WHEREişlemi eski ve yeni işlemleri ayıran bir cümle ile yaparsanız, 3. adımı atlayabilirsiniz.

  3. Yeni güncellemelerdeki benzersiz müşteri kimliklerini sıralı bir şekilde ayrı bir veri yapısına alın. Bir veri yapısına girmek için kullanabileceğiniz birkaç veri yapısı vardır new. Çift bağlantılı bir listeye ekleme sıralaması çok basittir, ancak bir ara hashtable kullanmak doğrusal zamana yakın bir şekilde çalışır veya orijinal diziyi yine de sıralıyorsanız, bunun bir setini almak kolaydır.

  4. Set farkı al new- oldfavori dilinin standart kitaplığını kullanarak. En sevdiğiniz dil bu algoritmayı standart kütüphanesinde içeriyor mu?

İşlem veritabanınızı güncelledikten sonra yapmak istediğiniz diğer şeyler kesinlikle SQL sorgularıdır.

3. adımla ilgili not: Verilerinizin niteliğini düşünün. Metin dosyanızın siparişleri kronolojik olarak listelediğini ve tipik bir haftada, customer_idartan sırada yeni verilen çok sayıda ilk kez müşteri olduğunu varsayalım . Diğer siparişlerin çoğunun az sayıda sadık tekrarlı müşteriden geldiğini varsayalım customer_id. Ardından girdileriniz çoğunlukla sıralanır. customer_idÇift bağlantılı bir listenin önüne düşük customer_idve arkadan yüksek yerleştirmeye çalıştığınız bir ekleme sıralaması , bu durumda pratikte iyi performans gösterir.


1
Müşterilerden ziyade yeni / aynı / güncellenmiş kaynaklarla daha fazla ilgileniyorum . Ama evet, fikir aynı olurdu.
Swartz

0

Sorunuzdan anladığım gibi, aslında kaynak_kimliği (+ info) ve müşterinin (id + info) "listesinin" var.

Böylece, kaynak başına müşteri listesini kolayca tutabilir ve kaynaktaki her listede son düğümü kontrol edebilirsiniz (son çalışma süresini bilmek için kodda müşterinize tarih alanı eklemeniz yeterlidir)

Ben SQL aşina değilim, bu yüzden benim örnek HashMapve Liste ile vermek ama eminim aynı fikir:, HashMap <Resource, List<Customer>>ne zaman ResourceresourceID anahtar olarak Customeriçermeli ve müşteri kimliği, bilgi ve işlem tarihi içermelidir.

Bu fikir sayesinde son çalışma süresini kolayca bilebilir ve herhangi bir kaynağı değiştirebilirsiniz (add \ remove resource \ customer).


0

Bir SqLite veritabanı kullanıyorsanız, toplu işin tarihini tablonun sütunu olarak da eklerseniz,

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

son X günde kullanılmayan kaynakları elde etmek için SQL kullanmak oldukça kolay olurdu

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

SQL'i test etmedim ama size bir fikir vermeli


0

Orijinal gönderiden, yutulan verilerin işlemin tarihini / saatini gösteren bir alanı yok gibi görünüyor ve dosyanın günlük, saatlik vb.

Ben veritabanı düzeyinde otomatik olarak oluşturulan bir SQL zaman damgası sütun ekleyerek veya veri ayıklar ve DB ekler kod tarafından bu ele. Sonra o zaman damgası sütununa bir dizin koymak ve onunla yapılır. DB motorunun "bu zamandan bu yana kaç işlem gerçekleşmediğini" veya "şu an ile o zaman arasında kaç işlem" sorusunu yanıtlamayı verimli hale getirme işini yapmasına izin verin.

Daha sonra, rapor etmek istediğiniz diferansiyelleri sorgulamak ve hesaplamak için bir iş zamanlarsınız. "Yeni" olan işlemler, "o zamandan beri yeni" olmasını istediğiniz tarihten önce DB'de kaydı olmayan işlemlerdir. Eski kayıtlar, kesme tarihinden itibaren hiçbir işlemi olmayan kayıtlardır.


-2

HashTable'lar bunun için değil mi? Yapmak istediğiniz tek şey, son aylarda hangi kaynakların kullanıldığının kayıtlarını tutmak ve son 18 ay içinde erişilmeyen kaynakları silmekse, Anahtarın kaynak_kimliği ve değerin son erişim tarihi.

> 18 aylık kayıtları arşivlemek için, karma tablodaki tüm kayıtları inceleyebilir ve yalnızca bu belirli kayıtları kaldırabilirsiniz (veya taşıyabilirsiniz). (bunu rapor geldiğinde haftalık olarak yapabilirsiniz)


Veritabanında bir şeyler saklıyorsam neden HashTable'a ihtiyaç duyuyorsunuz? DB kayıtlarına güncelleme yapabilirim. Daha çok bir durumla ilgileniyorum: iki veri kümesi al, iki set arasındaki farkları (eklenen, aynı, silinmiş) bulun. HashTable tekniği yeni ve "kaldırılmış" kayıtları bulmaya nasıl yardımcı olur?
Swartz

Tablolar veritabanında dizine eklenmişse, temel olarak perde arkasındaki HashTable'lardır. Her biri bir veri kümesini temsil eden 2 tablonuz varsa, bazı dış birleştirmeler yaparak yeni ve kaldırılmış kayıtlarınızı alabilirsiniz. Referans için buna bakın: i.stack.imgur.com/pxUO3.png . Resource_id sütununda dizinleriniz olduğundan emin olun ve oldukça hızlı olmalıdır. Bunu sıfırdan uygulamak zorunda kalırsanız, o zaman HashTables hala O (1) amortize zamanında arama / ekleme / silme yapabileceğiniz gibi gitmek için bir yol olacağını düşünüyorum. Bunu yapmanın daha etkili bir yolu düşünemiyorum.
Adrian Buzea

3
Bunu bir karma tabloya sıkıştırmanın ekstra adımları olmadan yaşlanmayı ele alan daha iyi veri yapıları vardır.

Biraz bahsetmek ister misin?
Adrian Buzea

@Snowman - Keşke birkaç kez daha oranı, keşke sadece bu yorumda kesinlikle katılıyorum
J-Boss
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.