อัลกอริทึมสำหรับกำหนดธุรกรรมระหว่างชุดข้อมูลรายสัปดาห์หรือไม่


9

ฉันพยายามพัฒนาเครื่องมือการรายงานขนาดเล็ก (พร้อม backend sqlite) ฉันสามารถอธิบายเครื่องมือนี้ในฐานะบัญชีแยกประเภท "ธุรกรรม" ได้ดีที่สุด สิ่งที่ฉันพยายามทำคือติดตาม "การทำธุรกรรม" จากการดึงข้อมูลรายสัปดาห์:

  • "ใหม่" (หรือเพิ่ม) - ทรัพยากรเป็นสิ่งใหม่สำหรับแอปของฉันเนื่องจากแอปของฉันอาจไม่ได้ติดตามทรัพยากรนี้มาก่อนเนื่องจากไม่ได้เห็นผ่านสารสกัด
  • "อัปเดต" (หรือกด) - มีการใช้งานล่าสุดของทรัพยากรนั้นอัปเดตช่วงเวลาการเก็บข้อมูลภายในสัปดาห์อื่น
  • "ลบ" (หรือลดลง) - รายการนี้ไม่เห็นการใช้งานตั้งแต่รายงานล่าสุด (ตัวเลือก แต่จะดีสำหรับการทำกราฟการเปลี่ยนแปลงความต้องการทรัพยากรในแต่ละสัปดาห์ต่อสัปดาห์)

ทั้งหมดที่ฉันได้รับคือสารสกัดข้อมูลรายสัปดาห์ (ไฟล์ที่คั่นด้วยไพพ์ไลน์) มาจากระบบเก็บถาวร / จัดการบันทึกแบบดั้งเดิมที่ฉันไม่สามารถควบคุมได้

แต่ละบรรทัดสามารถกลั่นโดยพื้นฐานนี้:
resource_id | resource info | customer_id | customer_info

ข้อมูลตัวอย่าง:

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

เป้าหมายคือทำให้ง่ายต่อการรายงานเกี่ยวกับทรัพยากรที่ไม่ได้เห็นการใช้งานสำหรับ X-month (ขึ้นอยู่กับการตีครั้งล่าสุด) มีระยะเวลาการเก็บรักษาที่ทรัพยากรถูกเก็บไว้รอบเพื่อความสะดวกในการเข้าถึงถ้าพวกเขากำลังได้รับความนิยม ทรัพยากรที่ไม่ได้เห็นการใช้งานเป็นเวลา 18 เดือนถูกทำเครื่องหมายว่าเป็นจดหมายเหตุระยะยาวที่อื่น

นี่จะเป็นปัญหาที่พบบ่อย สงสัยว่ามีอัลกอริทึมทั่วไปเพื่อกำหนดว่ามีอะไรใหม่ / เหมือนกัน / ลบออกระหว่างชุดข้อมูล (db ​​กับสารสกัดล่าสุด)

คำตอบ:


1

คำตอบของคุณคือ ... ใช่ มีอัลกอริทึมแบบง่ายที่คุณสามารถใช้ซึ่งไม่ต้องการสิ่งอื่นใด มันเป็นอัลกอริธึมมูลค่าปัจจุบันสุทธิ เป็นเรื่องง่ายที่จะนำไปใช้และสิ่งที่ต้องใช้ในตอนท้ายของฐานข้อมูลคือให้คุณประทับวันที่ข้อมูลรายสัปดาห์และเขียนแบบสอบถามง่ายๆหนึ่งรายการและฟังก์ชั่นวนซ้ำขนาดเล็กหรือลูปหรือคุณสามารถทำหนึ่งในโซลูชันอื่น ๆ

NPV = PV- (PV (CP / T) หรือมูลค่าปัจจุบันใหม่เท่ากับมูลค่าปัจจุบันคูณระยะเวลาปัจจุบัน (เดือนนับตั้งแต่รายการสุดท้าย) หารด้วยคำศัพท์ (เช่น 18 เดือน) เมื่อมูลค่าทรัพยากรลดลงถึง 0 มันเป็นมูลค่าปัจจุบันสุทธิ มีการใช้จ่าย

หากคุณให้ฉัน lang คุณต้องการในฉันจะโพสต์รหัสที่นี่ในการแก้ไข


ภาษาไม่ใช่สิ่งสำคัญ Ruby หรือ C ++ ถ้าฉันต้องเลือก หากคุณสามารถเขียนอัลกอริทึมใน HTML 4.0 Strict คุณจะเป็นฮีโร่ของฉัน ล้อเล่นเกี่ยวกับที่ส่วนสุดท้าย :)
Swartz

จะสนใจดูรหัส Ruby หรือ C ++ ขอบคุณ.
Swartz

0

หากคุณยังคงอัปเดตในแบ็กเอนด์ SQLite อยู่แล้วคุณสามารถเปลี่ยนการอัปเดตรายสัปดาห์เป็นตารางใหม่และเปรียบเทียบกับข้อมูลที่เก็บถาวรด้วยคำสั่งก่อนรวมเข้าด้วยกัน

ตัวอย่างการใช้ SQL เพื่อค้นหาส่วนเพิ่มเติมใหม่ในตาราง: /programming/2077807/sql-query-to-return-differences-between-two-tables

หากเขตข้อมูลในฐานข้อมูลของคุณเก็บวันที่ทำธุรกรรมคุณสามารถสอบถามผู้ใช้ทั้งหมดที่มีธุรกรรมในช่วง 18 เดือนที่ผ่านมา จากนั้นเก็บถาวรเป็นเพียงฐานข้อมูลแบบเต็ม หรือคุณสามารถสอบถามผู้ใช้ทั้งหมดที่ยังไม่ได้ดึงข้อมูลจากนั้นปล่อยพวกเขา การอัปเดตเป็นเพียงแถวใด ๆ ที่ประทับเวลาในสัปดาห์นี้


ดีกว่ามันเป็นโซลูชันที่ใช้ข้อมูลเป็นศูนย์กลางอย่างน้อย แต่ก็ยังมีราคาแพงเกินไป
J-Boss

ฉันใช้ sqlite ในขณะนี้เพราะมันง่ายที่จะเริ่มต้นด้วย สามารถสลับเป็น MySQL ได้อย่างง่ายดาย (หรือ PostgreSQL) หากใช้แบ็กเอนด์ที่ไม่มี SQL จะทำให้ทุกอย่างทำงานได้ดียิ่งขึ้น
Swartz

ดีความคิดของผมก็คือส่วนใหญ่ที่คุณกำลังแปลงไปแถวในฐานข้อมูลอยู่แล้ว หากคุณไม่จำเป็นต้องเรียกใช้จากหลาย ๆ กระบวนการพร้อมกันฉันไม่คิดว่าคุณต้องการเปลี่ยนไปใช้สิ่งที่มีน้ำหนักมากกว่า SQLite
Davislor

ไม่จำเป็นต้องประมวลผลพร้อมกัน แต่ฉันต้องเก็บข้อมูลเกี่ยวกับทรัพยากรไว้ที่ใดที่หนึ่ง SQL db ดูเหมือนจะเป็นตัวเลือกที่ดีอย่างไรก็ตามไม่มีอะไรขัดขวางฉันในการโหลดข้อมูลลงในประเภทข้อมูลใด ๆ สำหรับการประมวลผลเดลตา ทั้งหมดที่ฉันต้องการในตอนท้ายของการแยกแต่ละครั้งคือการหาว่ามีอะไรใหม่สิ่งที่ยังคงเหมือนเดิมและสิ่งที่หายไป ฉันสามารถหาวิธีอัปเดตบันทึกตามที่จำเป็นจากข้อมูลนี้
Swartz

หลังจากที่คุณแยกวิเคราะห์ข้อมูลและนำไปไว้ในฐานข้อมูลคุณอาจเขียนแบบสอบถามได้ง่ายกว่าใช้อัลกอริทึม ที่กล่าวว่าหากคุณต้องการโค้ดมันอัลกอริทึมที่คุณต้องการคือการตั้งค่าความแตกต่างและมีการนำไปใช้ใน C ++ STL ที่คุณสามารถใช้เพื่อทำมันในบรรทัดเดียวเมื่อคุณใส่ข้อมูลทั้งสองชุดลงในคอนเทนเนอร์ของ Vectorทางเลือกของคุณอาจจะเป็น
Davislor

0

แนวคิดทางเลือก:

  1. แยกวิเคราะห์รายการธุรกรรมของคุณลงในโครงสร้างข้อมูลบางประเภทเช่นอาร์เรย์ (ใน C ++ ให้คิดVectorและใน Java,. ArrayList)

  2. ทำแบบสอบถามเกี่ยวกับ SQL ของคุณแบ็กเอนด์เช่นและแพ็คเรียงรหัสลูกค้าที่แตกต่างกันออกเป็นชุดSELECT DISTINCT customer_id FROM Transactions ORDER BY customer_id oldหากคุณทำสิ่งเดียวกันโดยมีWHEREประโยคคั่นธุรกรรมเก่าและใหม่คุณสามารถข้ามขั้นตอนที่ 3

  3. รับรหัสลูกค้าที่ไม่ซ้ำกันจากการปรับปรุงใหม่ลงในโครงสร้างข้อมูลแยกตามลำดับ มีโครงสร้างข้อมูลสองสามอย่างที่คุณสามารถใช้เพื่อรับคือโครงสร้างข้อมูล, new. การจัดเรียงการแทรกลงในรายการที่มีการเชื่อมโยงสองครั้งนั้นง่ายมาก แต่การใช้ hashtable ระดับกลางจะทำงานใกล้เคียงกับเวลาเชิงเส้นหรือถ้าคุณกำลังเรียงลำดับอาร์เรย์ดั้งเดิมอยู่ดีการกำหนดออกมานั้นเป็นเรื่องง่าย

  4. ตั้งความแตกต่างnew- oldใช้ไลบรารีมาตรฐานของภาษาที่คุณชื่นชอบ ภาษาโปรดของคุณมีอัลกอริทึมนี้ในไลบรารีมาตรฐานหรือไม่?

สิ่งอื่น ๆ ที่คุณต้องทำคือแบบสอบถาม SQL แน่นอนหลังจากที่คุณปรับปรุงฐานข้อมูลธุรกรรมของคุณ

หมายเหตุเกี่ยวกับขั้นตอนที่ 3: พิจารณาลักษณะของข้อมูลของคุณ สมมติว่าไฟล์ข้อความของคุณแสดงรายการคำสั่งซื้อตามลำดับเวลาและในสัปดาห์ปกติมีลูกค้าครั้งแรกจำนวนมากที่ได้รับcustomer_idใบสั่งใหม่จากน้อยไปมาก สมมติว่าส่วนใหญ่คำสั่งอื่น ๆ จากจำนวนเล็ก ๆ customer_idของลูกค้าที่ทำซ้ำซื่อสัตย์กับที่ลดลง จากนั้นอินพุตของคุณจะถูกจัดเรียงเป็นส่วนใหญ่แล้ว การเรียงลำดับการแทรกที่คุณพยายามแทรกต่ำcustomer_idที่ด้านหน้าของรายการที่มีการเชื่อมโยงสองเท่าและสูงcustomer_idที่ด้านหลังในสถานการณ์นั้นจะทำได้ดีในทางปฏิบัติ


1
ฉันสนใจทรัพยากรใหม่ / ที่เหมือนกัน / ที่อัพเดตมากกว่าลูกค้า แต่ใช่ความคิดจะเหมือนกัน
Swartz

0

ตามที่ฉันเข้าใจจากคำถามของคุณคุณมี resource_id (+ ข้อมูล) และ "รายการ" ของลูกค้า (id + ข้อมูล)

ดังนั้นคุณสามารถเก็บรายชื่อลูกค้าต่อทรัพยากรและตรวจสอบโหนดสุดท้ายในแต่ละรายการในทรัพยากร (เพื่อที่จะทราบเวลาการทำงานล่าสุดคุณเพียงแค่ต้องเพิ่มเขตข้อมูลวันที่ให้กับลูกค้าของคุณในรหัส)

ฉันไม่คุ้นเคยกับ SQL ดังนั้นฉันจึงให้ตัวอย่างกับHashMapและรายการ แต่ฉันแน่ใจว่ามันเป็นแนวคิดเดียวกัน: HashMap <Resource, List<Customer>>เมื่อใดResourceควรมี resourceID เป็นคีย์และCustomerควรมี ID ลูกค้าข้อมูลและวันที่ดำเนินการ

ด้วยแนวคิดนี้คุณสามารถทราบเวลาการทำงานล่าสุดได้อย่างง่ายดายและสามารถแก้ไขทรัพยากรใด ๆ (เพิ่ม \ ลบทรัพยากร \ ลูกค้า)


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 ซึ่งสร้างอัตโนมัติที่ระดับฐานข้อมูลหรือด้วยรหัสที่แยกข้อมูลและส่วนแทรกลงในฐานข้อมูล จากนั้นคุณวางดัชนีลงในคอลัมน์การประทับเวลาและดำเนินการกับมัน ให้เอ็นจิ้น DB ทำงานอย่างมีประสิทธิภาพเพื่อตอบคำถาม "จำนวนธุรกรรมที่ไม่ได้เกิดขึ้นตั้งแต่เวลานี้" หรือ "จำนวนระหว่างเวลานี้กับเวลานั้น"

จากนั้นคุณกำหนดเวลางานเพื่อค้นหาและคำนวณส่วนต่างที่คุณต้องการรายงาน ธุรกรรมที่เป็น "ใหม่" เป็นธุรกรรมที่ไม่มีระเบียนใด ๆ ในฐานข้อมูลก่อนวันที่คุณจะถามว่า "ใหม่มาตั้งแต่" ระเบียนเก่าคือรายการที่ไม่มีธุรกรรมตั้งแต่วันที่ตัดออก


-2

นี่ไม่ใช่สิ่งที่ HashTables มีไว้เพื่ออะไร? หากสิ่งที่คุณต้องการทำคือเก็บบันทึกว่ามีการใช้ทรัพยากรใดในช่วงหลายเดือนที่ผ่านมาและลบทรัพยากรที่ไม่ได้เข้าถึงในช่วง 18 เดือนที่ผ่านมาคุณสามารถใช้ HashTable โดยที่คีย์คือ resource_id และค่าคือ วันที่เข้าถึงล่าสุด

สำหรับการเก็บถาวรระเบียน> 18 เดือนคุณสามารถทำตามบันทึกทั้งหมดในตารางแฮชและเพียงแค่ลบ (หรือย้าย) บันทึกเฉพาะเหล่านั้น (คุณสามารถทำสิ่งนี้ทุกสัปดาห์เมื่อมีรายงานเข้ามา)


ทำไมต้อง HashTable ถ้าฉันเก็บสิ่งต่าง ๆ ในฐานข้อมูล ฉันสามารถอัปเดตระเบียน db ได้ ฉันสนใจมากขึ้นในกรณี: นำชุดข้อมูลสองชุดค้นหาความแตกต่าง (สิ่งที่เพิ่มเข้ามายังคงเหมือนเดิมถูกลบ) ระหว่างสองชุด เทคนิค HashTable ช่วยในการค้นหาระเบียนใหม่และ "ลบ" อย่างไร
Swartz

หากตารางถูกทำดัชนีในฐานข้อมูลแล้วโดยพื้นฐานแล้วพวกเขายังเป็น HashTables ที่อยู่เบื้องหลัง หากคุณมี 2 ตารางแต่ละชุดจะแทนชุดข้อมูลคุณจะสามารถรับระเบียนใหม่และลบได้โดยทำการรวมภายนอกบางส่วน ดูนี้สำหรับการอ้างอิง: i.stack.imgur.com/pxUO3.png ตรวจสอบให้แน่ใจว่าคุณมีดัชนีในคอลัมน์ resource_id และควรรวดเร็ว หากคุณต้องใช้สิ่งนี้ตั้งแต่เริ่มต้นฉันคิดว่า HashTables ยังคงเป็นวิธีที่จะไปเพราะคุณสามารถทำการค้นหา / แทรก / ลบใน O (1) เวลาตัดจำหน่าย ไม่สามารถคิดวิธีที่มีประสิทธิภาพมากกว่านี้
Adrian Buzea

3
มีโครงสร้างข้อมูลที่ดีกว่าที่จัดการกับอายุโดยไม่มีขั้นตอนพิเศษของการยัดเยียดสิ่งนี้ลงในตารางแฮช

สนใจพูดถึงบางอย่าง?
Adrian Buzea

@Snowman - ฉันหวังว่าฉันจะได้อัตราที่อีกสองสามครั้งฉันจะได้เห็นด้วยอย่างยิ่งในความคิดเห็นนี้
J-Boss
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.