2012-10-19 3 views
8

मेरे पास दो इतिहास तालिकाएं हैं जो व्यक्तिगत मानों को ट्रैक करने के लिए एक संशोधन आईडी का उपयोग करके डेटाबेस मानों में परिवर्तन ट्रैक करती हैं। जैसेमूल्यों को भरते समय दो संस्करण-ट्रैकिंग तालिकाओं को विलय करना

तालिका 1:

rev | A | B 
================= 
1 | 100 | 'A' 
4 | 150 | 'A' 
7 | 100 | 'Z' 

तालिका 2:

rev | C | D 
================== 
1 | 200 | True 
5 | 0 | True 
8 | 0 | False 

लक्ष्य में दो तालिकाओं विलय करने के लिए होगा:

rev | A | B | C | D 
=============================== 
1 | 100 | 'A' | 200 | True 
4 | 150 | 'A' | 200 | True 
5 | 150 | 'A' | 0 | True 
7 | 100 | 'Z' | 0 | True 
8 | 100 | 'Z' | 0 | False 

विचार किया जा रहा है कि के लिए एक दिया के लिए संशोधन, मैं उस संशोधन से संबंधित मूल्यों को लेता हूं या उससे उच्चतम संशोधन कम करता हूं।

SQL क्वेरी जो मन में आता कुछ बाधा rev1 साथ दो तालिकाओं में शामिल होने < rev2 पार करने के लिए है, तो एक सबक्वेरी जहां rev1 = अधिकतम (rev1) प्रत्येक के लिए दिया rev2 का उपयोग कर पंक्तियों का चयन सदृश होगा ; इस क्वेरी को अपने समकक्ष के साथ rev2 और rev1 का आदान-प्रदान करने के साथ मिलकर; और आखिरकार rev1 = rev2 से डुप्लीकेट को फ़िल्टर करना।

प्रश्न हैं:

  • वहाँ में शामिल होने के इस प्रकार के लिए एक नाम है?
  • क्या SQL में इस प्रकार के शामिल होने के लिए कोई मुहावरे है, या प्रोग्रामेटिक रूप से ऐसा करना बेहतर होगा (जो निश्चित रूप से अधिक सरल और संभवतः अधिक कुशल होगा)?
+0

क्या RDBMS? कुछ को इस प्रकार के संचालन के लिए समर्थन है, इसलिए (विशेष रूप से यदि डेटा स्थान बड़ा है) यह वास्तव में डेटाबेस में अधिक कुशल हो सकता है। –

+0

तो आप क्वेरी नहीं चाहते हैं, लेकिन सिर्फ उन दो सवालों के जवाब? –

+0

डेटाबेस PostgreSQL है, हालांकि तकनीकी रूप से काम डीबी से स्वतंत्र होना चाहिए (वास्तव में यह होने वाला नहीं है)। और हाँ, केवल सवालों के जवाब में दिलचस्पी है, जब तक कि एक बहुत ही सरल क्वेरी नहीं है जिसे मैं देख रहा हूं। –

उत्तर

2

SQL Fiddle

select 
    coalesce(t1.rev, t2.rev) rev, 
    coalesce(a, lag(a, 1) over(order by coalesce(t2.rev, t1.rev))) a, 
    coalesce(b, lag(b, 1) over(order by coalesce(t2.rev, t1.rev))) b, 
    coalesce(c, lag(c, 1) over(order by coalesce(t1.rev, t2.rev))) c, 
    coalesce(d, lag(d, 1) over(order by coalesce(t1.rev, t2.rev))) d 
from 
    t1 
    full join 
    t2 on t1.rev = t2.rev 
order by rev 
1

इस उप द्वारा प्राप्त किया जा सकता

SELECT ISNULL(Table1.rev,Table2.rev) AS rev 
,ISNULL(A,(SELECT TOP 1 A FROM Table1 AS T1 WHERE ISNULL(Table1.rev,Table2.rev) > T1.rev AND A IS NOT NULL ORDER BY rev DESC)) AS A 
,ISNULL(B,(SELECT TOP 1 B FROM Table1 AS T1 WHERE ISNULL(Table1.rev,Table2.rev) > T1.rev AND B IS NOT NULL ORDER BY rev DESC)) AS B 
,ISNULL(C,(SELECT TOP 1 C FROM Table2 AS T2 WHERE ISNULL(Table1.rev,Table2.rev) > T2.rev AND C IS NOT NULL ORDER BY rev DESC)) AS C 
,ISNULL(D,(SELECT TOP 1 D FROM Table2 AS T2 WHERE ISNULL(Table1.rev,Table2.rev) > T2.rev AND D IS NOT NULL ORDER BY rev DESC)) AS D 
FROM Table1 
FULL OUTER JOIN Table2 
ON Table1.rev = Table2.rev 
+0

'isnull' वैध postgresql वाक्यविन्यास मान्य नहीं है –

0

वहाँ कोई विशेष है प्रकार में शामिल होने क्वेरी की इस प्रकार की संभाल करने के लिए प्रश्नों। आपको इसे जटिल क्वेरी या प्रोग्रामेटिक रूप से करना है। नीचे दिए गए उदाहरण के लिए, इस समस्या के लिए पीएल/पीजीएसक्यूएल कोड का एक उदाहरण नीचे दिया गया है।

CREATE OR REPLACE FUNCTION getRev(OUT rev INT, OUT A INT, OUT B CHAR, OUT C INT, OUT D BOOL) RETURNS SETOF record STABLE AS 
$BODY$ 
DECLARE 
    c1 SCROLL CURSOR FOR SELECT * FROM Table1 ORDER BY rev; 
    c2 SCROLL CURSOR FOR SELECT * FROM Table2 ORDER BY rev; 
    r1 Table1%ROWTYPE; 
    r1c Table1%ROWTYPE; 
    r2 Table2%ROWTYPE; 
    r2c Table2%ROWTYPE; 
BEGIN 
    OPEN c1; 
    OPEN c2; 
    FETCH c1 INTO r1; 
    FETCH c2 INTO r2; 
    r1c := r1; 
    r2c := r2; 
    WHILE r1 IS NOT NULL AND r2 IS NOT NULL 
    LOOP 
    CASE 
    WHEN r1.rev = r2.rev THEN 
     rev := r1.rev; 
     A := r1.a; 
     B := r1.b; 
     C := r2.c; 
     D := r2.d; 
     FETCH c1 INTO r1c; 
     FETCH c2 INTO r2c; 
     CASE 
     WHEN r1c.rev = r2c.rev THEN 
     r1 := r1c; 
     r2 := r2c; 
     WHEN r1c.rev < r2c.rev THEN 
      r1 := r1c; 
     FETCH PRIOR FROM c2 INTO r2c; 
    ELSE 
      r2 := r2c; 
     FETCH PRIOR FROM c1 INTO r1c; 
     END CASE; 
    WHEN r1.rev < r2.rev THEN 
     WHILE r1c IS NOT NULL AND r1c.rev < r2.rev LOOP 
     r1 := r1c; 
     FETCH c1 INTO r1c; 
     END LOOP; 
     rev := r2.rev; 
     A := r1.a; 
     B := r1.b; 
     C := r2.c; 
     D := r2.d; 
     r1 := r1c; 
    ELSE 
     WHILE r2c IS NOT NULL AND r2c.rev < r1.rev LOOP 
     r2 := r2c; 
     FETCH c2 INTO r2c; 
     END LOOP; 
     rev := r1.rev; 
     A := r1.a; 
     B := r1.b; 
     C := r2.c; 
     D := r2.d; 
     r2 := r2c; 
    END CASE; 
    RETURN NEXT; 
    END LOOP; 
    CLOSE c1; 
    CLOSE c2; 
    RETURN; 
END 
$BODY$ 
LANGUAGE 'plpgsql'; 

यह ओ (लंबाई (तालिका 1) + लंबाई (तालिका 2) में चलाना चाहिए)।

"केस जब r1.rev = r2.rev" में मुश्किल हिस्सा नोट करें: हमें यह चुनना होगा कि हम कौन सी तालिका अगले पुनरावृत्ति के लिए स्कैन जारी रखेंगे। दोनों टेबलों में उपलब्ध सभी संशोधित संख्याओं को प्राप्त करने के लिए कर्सर के बाद सबसे छोटा पुनर्विक्रय वाला एक सही है। आप निश्चित रूप से सी या सी ++ में कोडिंग करके बेहतर प्रदर्शन प्राप्त कर सकते हैं।

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