2012-01-23 9 views
11

यहां एक प्रश्न है कि मैं अपने दिमाग को खत्म कर रहा हूं। मान लें कि मेरे पास एक सारणी है जिसमें टाइमस्टैम्प की एक श्रृंखला है और प्राथमिक कुंजी के रूप में एक भाग संख्या है। तालिका में वृद्धिशील परिवर्तन होते हैं, जिसका अर्थ है कि प्रत्येक टाइमस्टैम्प के लिए, यदि कोई फ़ील्ड बदलता है, तो वह परिवर्तन दर्ज किया जाता है। यदि फ़ील्ड नहीं बदलता है, तो नए टाइमस्टैम्प के लिए यह पूर्ण है। यहां बुनियादी विचार है।डेटाबेस: अंतिम गैर-शून्य प्रविष्टियों का चयन करें

part | timestamp | x-pos | y-pos | status 
------+-----------+-------+-------+-------- 
a5 |  151 |  5 | 15 |  g 
a5 |  153 | NULL | 17 | NULL 

(part, timestamp) प्राथमिक कुंजी है। दूसरे रिकॉर्ड में NULL एस उन मानों को इंगित करता है जो पहले रिकॉर्ड के बाद अपरिवर्तित हैं।

मैं जो करने में सक्षम होना चाहता हूं वह हिस्सा द्वारा समूहित प्रत्येक फ़ील्ड के लिए सबसे हाल के मानों का चयन करना है। उदाहरण के लिए, उपर्युक्त प्रविष्टियों को देखते हुए, परिणाम भाग 5 के लिए 153,5,17, जी होंगे।

अभी तक, मैंने यह एक साथ क्वेरी हैक की है।

((SELECT x-pos FROM part_changes WHERE x-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) 

    UNION 

    (SELECT y-pos FROM part_changesWHERE y-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) 

    UNION 

    (SELECT status FROM part_changes WHERE status IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1)) 

लेकिन यह एक एकल कॉलम देता है, जिसका अर्थ है कि मैं आयोजन के लिए समूह का उपयोग कर सकता हूं।

चीज करने का एक और अधिक शानदार तरीका होना चाहिए, जैसे कि रचनात्मक तरीके से COALESCE या IS NULL का उपयोग करना। लेकिन मैं अटक गया हूं और इसे समझ नहीं सकता। किसी को कोई विचार आया?

और नहीं, मैं डेटाबेस संरचना को नहीं बदल सकता।

संपादित करें: ruakh का सही विचार है। एकमात्र समस्या अब भाग से ग्रुप कर रही है। मुझे कई हिस्सों द्वारा समूहित करने के लिए LIMIT 1 के आसपास नहीं लग रहा है। कोई विचार?

mdahlman, मैं postgresql में विश्लेषणात्मक कार्यों से परिचित नहीं हूं। इसलिए, यदि वह समाधान एक जटिल क्वेरी से आसान होगा, तो हर तरह से अपना विचार पोस्ट करें।

संपादित करें 2: सहायता के लिए सभी को धन्यवाद। मुझे लगता है कि मुझे जो कुछ करना है, उसके बारे में मुझे काफी समझ है।

+1

आपको यह निर्दिष्ट करना चाहिए कि विश्लेषणात्मक कार्यों की अनुमति है या नहीं। उनके साथ, जवाब सरल होना चाहिए। उनके बिना ... यह कठिन होगा। – mdahlman

+0

क्या कोई सीमा है कि कितने शून्य मूल्य हो सकते हैं? यदि कोई सीमा होगी तो यह कुछ बाएं जुड़ने के साथ एक समाधान होगा .. अच्छा नहीं है लेकिन यह किया जा सकता है;) – rauschen

+0

मुझे नहीं लगता कि एक सीमा है। वास्तव में, फ़ील्ड में से एक में विशाल बहुमत (99% की तरह कुछ) रिकॉर्ड के रूप में पूर्ण है। –

उत्तर

5

UNION का उपयोग करने के बजाय, ऐसा लगता है कि आप वास्तव में फ़ील्ड सूची में सबक्वायरी चाहते हैं। यही है, (SELECT ...) UNION (SELECT ...) UNION (SELECT ...) के बजाय, आप SELECT (SELECT ...), (SELECT ...), (SELECT ...) चाहते हैं।


उदाहरण के लिए:

SELECT part, 
     (SELECT x_pos 
      FROM part_changes 
      WHERE part = pc.part 
      AND x_pos IS NOT NULL 
      ORDER 
      BY timestamp DESC 
      LIMIT 1 
     ) AS x_pos, 
     (SELECT y_pos 
      FROM part_changes 
      WHERE part = pc.part 
      AND y_pos IS NOT NULL 
      ORDER 
      BY timestamp DESC 
      LIMIT 1 
     ) AS y_pos, 
     (SELECT status 
      FROM part_changes 
      WHERE part = pc.part 
      AND status IS NOT NULL 
      ORDER 
      BY timestamp DESC 
      LIMIT 1 
     ) AS status 
    FROM (SELECT DISTINCT 
       part 
      FROM part_changes 
     ) AS pc 
; 

लेकिन इस बिंदु पर मैं वास्तव में एक संग्रहीत प्रक्रिया लिखने पर विचार होगा।


वैकल्पिक रूप से:

SELECT DISTINCT 
     part, 
     FIRST_VALUE(x_pos) OVER 
     (PARTITION BY part 
       ORDER BY CASE WHEN x_pos IS NULL 
          THEN NULL 
          ELSE TIMESTAMP 
         END DESC NULLS LAST 
     ) AS x_pos, 
     FIRST_VALUE(y_pos) OVER 
     (PARTITION BY part 
       ORDER BY CASE WHEN y_pos IS NULL 
          THEN NULL 
          ELSE TIMESTAMP 
         END DESC NULLS LAST 
     ) AS y_pos, 
     FIRST_VALUE(status) OVER 
     (PARTITION BY part 
       ORDER BY CASE WHEN status IS NULL 
          THEN NULL 
          ELSE TIMESTAMP 
         END DESC NULLS LAST 
     ) AS status 
    FROM part_changes 
; 
+0

ऐसा लगता है कि एक समस्या हल हो गई है। धन्यवाद। हालांकि, मुझे यकीन नहीं है कि भाग संख्या द्वारा समूहबद्ध करने के लिए 'समूह द्वारा' कहाँ जाना होगा। कोई विचार? –

+0

@ बैटमैस्टरसन: उस तरह का विवरण एसक्यूएल की बोली पर निर्भर करेगा। 'ORDER BY ... LIMIT 1' के उपयोग से, मुझे लगता है कि आप MySQL को लक्षित कर रहे हैं; क्या वो सही है? (यदि ऐसा है - या यदि नहीं - आपको अपने प्रश्न पर टैग संपादित करना चाहिए।) – ruakh

+0

आह, अच्छा सवाल है। यह postgreSQL है। मैं पोस्ट अपडेट करूंगा। –

0

ruakh सही है। वैकल्पिक: एसक्यूएल-सीएलआर का उपयोग कर उपयोगकर्ता द्वारा परिभाषित कुल लिखें। यह कुल आपकी पंक्तियों पर नीचे-शीर्ष-शीर्ष चला सकता है और प्रत्येक कॉलम के पहले गैर-शून्य मान को याद रख सकता है।

आप इसे एप्लिकेशन में भी कर सकते हैं। कहें, 10 पंक्तियों के बैचों में सॉर्ट किए गए क्रम में अपने प्रोग्राम अनुरोध पंक्तियां बनाएं। उपरोक्त वर्णित इन बैचों को कुल मिलाएं। यदि वर्तमान बैच के बाद एक नल-कॉलम किया जाता है तो अगली बैच मिलती है।

+0

एसक्यूएल-सीएलआर पोस्टग्रेएसक्यूएल के साथ ओपी की मदद नहीं करेगा। हालांकि, यह अंतर्निर्मित सामान के साथ किया जा सकता है, और आपके द्वारा वर्णित ('FIRST') [PostgreSQL विकी पर] का एक उदाहरण है (http://wiki.postgresql.org/wiki/First_%28aggregate%29)। –

+0

मैं चाहता हूं कि SQL सर्वर पहले था। – usr

2

केवल एक भाग के लिए यह आपको एक उत्तर देना चाहिए ..धन्यवाद ruakh

लिए लेकिन मैं इस संस्करण पसंद नहीं .. प्रासंगिक टाइम स्टांप की

SELECT 
    (SELECT timestamp FROM part_changes WHERE part = $part 
    ORDER BY timestamp DESC 
    LIMIT 1) as timestamp, 

    (SELECT x-pos FROM part_changes WHERE part = $part and x-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) as xpos, 

    (SELECT y-pos FROM part_changes WHERE part = $part and y-pos IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1) as ypos, 

    (SELECT status FROM part_changes WHERE part = $part and status IS NOT NULL 
    ORDER BY timestamp DESC 
    LIMIT 1)) as status 
+0

मैं मानता हूं कि प्रत्येक भाग के लिए इसे दोबारा करना मुश्किल है। – mvrak

+0

मुझे लगता है कि मैं बस एक फ़ंक्शन लिख सकता हूं जो भाग संख्या में तर्क के रूप में लेता है, फिर इसका उपयोग करें। धन्यवाद। –

1

सूची:

select max timestamp from part_changes where x_POS is not null group by part 

आप इस के लिए एक दृश्य बना सकते हैं: देता है यह View1

फोन
SELECT part_changes.part, part_changes.x-pos 
FROM part_changes left join view1 on part_changes.part = view1.part 
WHERE x-pos IS NOT NULL 
AND part_changes.timestamp = view1.timestamp 
GROUP BY part_changes.part 

देखें कि मैं कहां जा रहा हूं? इससे आपको एक्स-पॉज़ के लिए पूरी सूची मिलनी चाहिए।

+0

दिलचस्प विचार। मैंने अपने लाभ में कुछ जुड़ने की शून्य-उन्मूलन गुणवत्ता का उपयोग करने के बारे में सोचा, लेकिन मुझे नहीं पता था कि कहां से शुरू करना है। मैं थोड़ा सा प्रयोग करूँगा। मेरी एकमात्र चिंता यह है कि मेरे मामले में, वास्तव में बहुत अधिक कॉलम हैं। पोस्ट में उदाहरण एक सरलीकृत संस्करण था। क्या बहुत से लोगों को स्मृति के साथ समस्या होगी? –

+0

यदि आपके पास कुछ सौ हैं तो यह हो सकता है ... मैंने समूह को शामिल करने के लिए अभी भी अपनी पोस्ट संपादित की है। अब जब मैं इसके बारे में सोचता हूं, मुझे लगता है कि यह आपको वही देगा जो आप x_pos के लिए चाहते हैं। हालांकि सम्मानित! – mvrak

+0

मेरा मानना ​​है कि केवल 15 फ़ील्ड हैं, और प्रति दिन हजारों रिकॉर्ड हैं। मैं इसे आज़माउंगा। यह वही हो सकता है जो मुझे चाहिए। –

संबंधित मुद्दे