2009-11-02 10 views
5

मेरे पास एक सारणी है जो एक वर्ग 3 डेटाबेस में खेले जाने वाले गेम की एक सूची है। फ़ील्ड "डेटटाइम" गेम समाप्त होने पर एक डेटाटाइम है। फ़ील्ड "अवधि" गेम की अवधि के सेकंड की संख्या है। मैं जानना चाहता हूं कि पिछले 24 घंटों में से किस प्रतिशत में कम से कम 5 गेम चल रहे थे। मैं पता लगा बताने के लिए कई खेल एक निश्चित समय पर चल रहे हैं:स्क्लाइट 3: कार्टेशियन की तारीख

select count(*) 
from games 
where strftime('%s',datetime)+0 >= 1257173442 and 
     strftime('%s',datetime)-duration <= 1257173442 

अगर मैं एक तालिका कि बस हर दूसरे (या हर 30 सेकंड या कुछ और) मैं एक जानबूझकर cartisian उत्पाद कर सकता है की एक सूची थी इस तरह:

select count(*) 
from (
    select count(*) as concurrent, d.second 
    from games g, date d 
    where strftime('%s',datetime)+0 >= d.second and 
     strftime('%s',datetime)-duration <= d.second and 
     d.second >= strftime('%s','now') - 24*60*60 and 
     d.second <= strftime('%s','now') 
    group by d.second) x 
where concurrent >=5 

वहाँ के लिए एक रास्ता मक्खी पर इस तिथि तालिका बनाने के है? या मैं को वास्तव में एक नई तालिका बनाने के बिना इस पर एक समान प्रभाव प्राप्त कर सकता हूं जो कि इस हफ्ते सभी सेकंड की सूची है?

धन्यवाद

उत्तर

2

शानदार सवाल!

यहां एक प्रश्न है कि मैं सोचता हूं कि आपको एक अलग तालिका का उपयोग किए बिना क्या चाहता है। ध्यान दें कि यह अवांछित है (इसलिए शायद त्रुटियां हैं) और मैंने माना है कि डेटाटाइम एक int कॉलम है जो # सेकंड के साथ स्ट्रेटटाइम के टन से बचने के लिए है। प्रत्येक खेल के समय शुरू में समवर्ती खेल की # के साथ, और अंत समय में समवर्ती खेल की # के साथ एक:

select sum(concurrent_period) from (
    select min(end_table.datetime - begin_table.begin_time) as concurrent_period 
    from (
    select g1.datetime, g1.num_end, count(*) as concurrent 
    from (
     select datetime, count(*) as num_end 
      from games group by datetime 
    ) g1, games g2 
    where g2.datetime >= g1.datetime and 
      g2.datetime-g2.duration < g1.datetime and 
      g1.datetime >= strftime('%s','now') - 24*60*60 and 
      g1.datetime <= strftime('%s','now')+0 
) end_table, (
    select g3.begin_time, g1.num_begin, count(*) as concurrent 
    from (
     select datetime-duration as begin_time, 
      count(*) as num_begin 
      from games group by datetime-duration 
    ) g3, games g4 
    where g4.datetime >= g3.begin_time and 
      g4.datetime-g4.duration < g3.begin_time and 
      g3.begin_time >= strftime('%s','now') - 24*60*60 and 
      g3.begin_time >= strftime('%s','now')+0 
) begin_table 
    where end_table.datetime > begin_table.begin_time 
     and begin_table.concurrent < 5 
     and begin_table.concurrent+begin_table.num_begin >= 5 
     and end_table.concurrent >= 5 
     and end_table.concurrent-end_table.num_end < 5 
    group by begin_table.begin_time 
) aah 

मूल विचार दो तालिकाओं बनाना है। फिर तालिकाओं में एक साथ शामिल हों और केवल "महत्वपूर्ण बिंदुओं" पर पंक्तियां लें, जहां समवर्ती खेलों का # पार हो जाता है। प्रत्येक महत्वपूर्ण प्रारंभिक समय के लिए, जल्द ही महत्वपूर्ण अंत समय लें और उम्मीद है कि कम से कम 5 गेम चल रहे थे समवर्ती।

आशा है कि सहायक होने के लिए बहुत गड़बड़ नहीं है!

0

क्यों आप तारीख ट्रिम नहीं है और केवल समय रखने के लिए, आप किसी भी तारीख हर बार अद्वितीय है के लिए अपने डेटा को फ़िल्टर करता है, तो। इस तरह आपको केवल 1 से 86400 तक की एक तालिका की आवश्यकता होगी (या यदि आप बड़े अंतराल लेते हैं तो कम), आप अंतराल को परिभाषित करने के लिए "से" और "से" दो कॉलम बना सकते हैं। मैं SQLite फ़ंक्शंस से परिचित नहीं हूं लेकिन मैनुअल के अनुसार आपको इस प्रारूप के साथ स्ट्रैटाइम फ़ंक्शन का उपयोग करना होगा: एचएच: एमएम: एसएस।

3

सबसे पहले, मैं फ्लाई पर एक टेबल बनाने या अतिरिक्त तालिका की सहायता के बिना आपकी समस्या का समाधान करने का कोई तरीका नहीं सोच सकता। माफ़ कीजिये।

मेरा सुझाव है कि आप स्थिर संख्या तालिका पर भरोसा करें।

प्रारूप के साथ एक निश्चित तालिका बनाएँ:

CREATE TABLE Numbers (
    number INTEGER PRIMARY KEY 
); 

24 घंटों में सेकंड की संख्या (24 * 60 * 60 = 84600) के साथ यह आबाद। एक के बिना

select count(*) 
    from (
     select count(*) as concurrent, strftime('%s','now') - 84601 + n.number second 
      from games g, numbers n 
     where strftime('%s',datetime)+0 >= strftime('%s','now') - 84601 + n.number and 
       strftime('%s',datetime)-duration <= strftime('%s','now') - 84601 + n.number 
     group by second) x 
where concurrent >=5 

: होने के लिए अब नंबर तालिका संख्या 1 है

insert into numbers default values; 

84600. आपकी क्वेरी के माध्यम से उन्हें संशोधित किया जाएगा: मैं किसी भी पटकथा भाषा का उपयोग करने वाले डालने कथन का उपयोग करने के लिए होगा मिश्रण में प्रक्रियात्मक भाषा, यह सबसे अच्छा है जो आप करने में सक्षम होंगे, मुझे लगता है।

+0

संख्या तालिका चाल आम आप पुनरावर्ती CTE/सबक्वेरी फैक्टरिंग का उपयोग करते हैं नहीं कर सकते ... –

+0

हाँ, और संख्या तालिका इस विशेष परिदृश्य की तुलना में अधिक उपयोगी हो जाएगा। आप इसे हमेशा सीमित कर सकते हैं और केवल आपको आवश्यक सबसेट प्राप्त कर सकते हैं: 'नंबर सीमा 100 से संख्या का चयन करें;' यह सिर्फ एक सुविधाजनक निर्माण है ... – cethegeek

2

केविन ने मुझे वहां पंचलाइन पर छोड़ दिया (+1), लेकिन मैं इस बदलाव को पोस्ट करूंगा क्योंकि यह कम से कम थोड़ा अलग है।

प्रमुख विचारों

  • गुण समय और 'polarity' के साथ घटनाओं की एक धारा के लिए डेटा के मानचित्र में (= शुरू करने या खेल के अंत)
  • कितने खेल रहे हैं की एक चल कुल रखें हैं प्रत्येक घटना के समय (यह ईवेंट स्ट्रीम पर स्वयं-जुड़ने के द्वारा किया जाता है)
  • ईवेंट के समय खोजें (जहां केविन कहते हैं) संक्रमण 5 तक, या नीचे 4
  • एक छोटी सी चाल: सभी नीचे-से-4 बार जोड़ें और टी को दूर करें अप-टू-5s वह - क्रम
  • परिणाम खुला

मैं sqllite नहीं है 5 या अधिक खेल के साथ बिताया सेकंड की संख्या है महत्वपूर्ण नहीं है, इसलिए मैं MySQL के साथ परीक्षण किया गया है , और मैंने कुछ स्वच्छता को बचाने के लिए समय खिड़की को सीमित करने के लिए परेशान नहीं किया है। संशोधित करना मुश्किल नहीं होना चाहिए।

इसके अलावा, और अधिक महत्वपूर्ण बात यह नहीं है कि अगर गेम की शुरुआत या अंत में गेम खुले हैं तो मुझे क्या नहीं करना चाहिए!

कुछ मुझे बताता है कि यहां होने के लिए एक बड़ा सरलीकरण है, लेकिन मैंने इसे अभी तक नहीं देखा है।

SELECT SUM(event_time) 
FROM (
SELECT -ga.event_type * ga.event_time AS event_time, 
    SUM( ga.event_type * gb.event_type) event_type 
FROM 
    (SELECT UNIX_TIMESTAMP(g1.endtime - g1.duration) AS event_time 
      , 1 event_type 
     FROM games g1 
     UNION 
     SELECT UNIX_TIMESTAMP(g1.endtime) 
      , -1 
     FROM games g1) AS ga, 
    (SELECT UNIX_TIMESTAMP(g1.endtime - g1.duration) AS event_time 
      , 1 event_type 
     FROM games g1 
     UNION 
     SELECT UNIX_TIMESTAMP(g1.endtime) 
      , -1 
     FROM games g1) AS gb 
WHERE 
    ga.event_time >= gb.event_time 
GROUP BY ga.event_time 
HAVING SUM(ga.event_type * gb.event_type) IN (-4, 5) 
) AS gr 
संबंधित मुद्दे