2009-03-02 11 views
8

में शामिल करने के लिए कैसे परिवर्तित करें मेरे पास 1: n रिश्ते के साथ दो टेबल हैं: "सामग्री" और "संस्करण-सामग्री-डेटा" (उदाहरण के लिए, एक आलेख इकाई और उस आलेख के बनाए गए सभी संस्करण) । मैं एक ऐसा दृश्य बनाना चाहता हूं जो प्रत्येक "सामग्री" का शीर्ष संस्करण प्रदर्शित करता हो।एक एसक्यूएल सबक्वायरी को

 
SELECT 
    t1.id, 
    t1.title, 
    t1.contenttext, 
    t1.fk_idothertable 
    t1.version 
FROM mytable as t1 
WHERE (version = (SELECT MAX(version) AS topversion 
        FROM mytable 
        WHERE (fk_idothertable = t1.fk_idothertable)))

सबक्वेरी वास्तव में एक ही तालिका जो किसी विशेष आइटम का उच्चतम संस्करण के अर्क के लिए एक प्रश्न है:

वर्तमान में मैं इस क्वेरी (एक सरल सबक्वेरी के साथ) का उपयोग करें। ध्यान दें कि संस्करण वाले आइटमों में वही fk_idothertable होगा।

एसक्यूएल सर्वर में मैं इस क्वेरी का एक अनुक्रमित दृश्य बनाने की कोशिश की लेकिन ऐसा लगता है मैं सक्षम के बाद से सबक्वेरी अनुक्रमित विचारों में अनुमति नहीं है नहीं कर रहा हूँ। तो ... यह मेरा प्रश्न है ... क्या आप इस क्वेरी को जॉइन के साथ किसी प्रकार की क्वेरी में बदलने का तरीका सोच सकते हैं?

ऐसा लगता है कि अनुक्रमित विचारों को शामिल नहीं कर सकते हैं:

  • सबक्वेरी
  • आम तालिका भाव
  • व्युत्पन्न टेबल
  • होने खंड

मैं बेताब हूँ। किसी अन्य विचार का स्वागत है :-)

बहुत बहुत धन्यवाद!

+0

आपकी उपकुमारी सही है? मुझे केवल –

+0

संदर्भित एक तालिका दिखाई देती है, हां, एक ही तालिका में एक सबक्वायरी है जो एक आइटम के अधिकतम संस्करण को निकालती है जो एक ही fk_idothertable – sachaa

+0

btw साझा करती है ... fk_idothertable मास्टर टेबल – sachaa

उत्तर

13

यह शायद नहीं होगा अगर टेबल पहले से ही उत्पादन में है तो मदद करें, लेकिन इसका मॉडल करने का सही तरीका संस्करण = 0 को स्थायी संस्करण बनाना है और हमेशा OLDER सामग्री के संस्करण को बढ़ा देना है।तो जब आप एक नया संस्करण सम्मिलित आप कहेंगे:

UPDATE thetable SET version = version + 1 WHERE id = :id 
INSERT INTO thetable (id, version, title, ...) VALUES (:id, 0, :title, ...) 

तो इस क्वेरी सिर्फ

SELECT id, title, ... FROM thetable WHERE version = 0 

नहीं सबक्वेरी, कोई मैक्स एकत्रीकरण होगा। आप हमेशा जानते हैं कि वर्तमान संस्करण क्या है। नया रिकॉर्ड डालने के लिए आपको अधिकतम (संस्करण) का चयन नहीं करना पड़ेगा।

+1

बहुत चालाक विचार। धन्यवाद जो! – sachaa

+0

बहुत साफ! अच्छा हुआ। –

-1

इस तरह ... मुझे लगता है कि सबक्वायरी में 'mytable' एक अलग वास्तविक तालिका थी ... इसलिए मैंने इसे mytable2 कहा। यदि यह वही टेबल था तो यह अभी भी काम करेगा, लेकिन फिर मुझे लगता है कि fk_idothertable बस 'id' होगा।


SELECT 
    t1.id, 
    t1.title, 
    t1.contenttext, 
    t1.fk_idothertable 
    t1.version 
FROM mytable as t1 
    INNER JOIN (SELECT MAX(Version) AS topversion,fk_idothertable FROM mytable2 GROUP BY fk_idothertable) t2 
     ON t1.id = t2.fk_idothertable AND t1.version = t2.topversion 

आशा इस

+0

सबक्वायरी वास्तव में एक ही तालिका के लिए एक क्वेरी है जो एक विशिष्ट आइटम के उच्चतम संस्करण को निकालती है। ध्यान दें कि वही संस्करण वाले आइटमों में एक ही fk_idothertable होगा। – sachaa

0

मैं यह कैसे कुशल होगा पता नहीं है में मदद करता है, लेकिन:

 
SELECT t1.*, t2.version 
FROM mytable AS t1 
    JOIN (
     SElECT mytable.fk_idothertable, MAX(mytable.version) AS version 
     FROM mytable 
    ) t2 ON t1.fk_idothertable = t2.fk_idothertable 
+0

आपको एक समूह की आवश्यकता है। –

+0

लेकिन फिर भी ... इस क्वेरी के समूह के साथ भी मूल रूप से mytable + सभी आइटम के अधिकतम संस्करण से सभी सूची आइटम लौटाता है। यह आइटम को उच्चतम संस्करण के साथ वापस नहीं करता है। – sachaa

0

आप अधिकतम एक मेज उर्फ ​​कि द्वारा समूह करता है बनाने के लिए कर सकता है।

SELECT 
    t1.id, 
    t1.title, 
    t1.contenttext, 
    t1.fk_idothertable 
    t1.version 
FROM mytable as t1 JOIN 
    (SELECT fk_idothertable, MAX(version) AS topversion 
    FROM mytable 
    GROUP BY fk_idothertable) as t2 
ON t1.version = t2.topversion 
3

हो सकता है कि कुछ इस तरह:

वह कुछ इस तरह लग सकता है?

SELECT 
    t2.id, 
    t2.title, 
    t2.contenttext, 
    t2.fk_idothertable, 
    t2.version 
FROM mytable t1, mytable t2 
WHERE t1.fk_idothertable == t2.fk_idothertable 
GROUP BY t2.fk_idothertable, t2.version 
HAVING t2.version=MAX(t1.version) 

बस एक जंगली अनुमान ...

+0

आपकी प्रतिक्रिया के लिए धन्यवाद। मुझे वास्तव में आपके समाधान की लालित्य पसंद आया लेकिन जब मैं इसे निष्पादित करता हूं तो मुझे मिलता है: कॉलम 'mytable.id' चयनित सूची में अमान्य है क्योंकि यह या तो कुल कार्य या ग्रुप बाय क्लॉज में निहित नहीं है। कोई अन्य विचार? – sachaa

+0

बस SELECT में सभी फ़ील्ड को समूह में जोड़ें - AFAIK मानक आवश्यकताएं हैं, लेकिन ऐसे डीबीएमएस हैं जिन्हें इसकी आवश्यकता नहीं है। – jpalecek

+0

यदि मैं ऐसा करता हूं, जब भी इस आइटम के संस्करणों के बीच शीर्षक बदलता है (उसी fk_idothertable के साथ) परिणाम में दो बार अपरिपक्व होगा (अलग-अलग शीर्षक + अलग संस्करण) – sachaa

0

मुझे लगता है कि FerranB करीब था लेकिन काफी समूहीकरण का अधिकार नहीं:

with 
latest_versions as (
    select 
     max(version) as latest_version, 
     fk_idothertable 
    from 
     mytable 
    group by 
     fk_idothertable 
) 
select 
    t1.id, 
    t1.title, 
    t1.contenttext, 
    t1.fk_idothertable, 
    t1.version 
from 
    mytable as t1 
    join latest_versions on (t1.version = latest_versions.latest_version 
     and t1.fk_idothertable = latest_versions.fk_idothertable); 

एम

+0

धन्यवाद मार्क। यह क्वेरी सही परिणाम लौटाती है लेकिन चूंकि यह "सामान्य तालिका अभिव्यक्ति" का उपयोग करती है SQL सर्वर में अनुक्रमित दृश्य बनाने के लिए मेरे लिए मान्य नहीं है। – sachaa

0
If SQL Server accepts LIMIT clause, I think the following should work: 
SELECT 
    t1.id, 
    t1.title, 
    t1.contenttext, 
    t1.fk_idothertable 
    t1.version 
FROM mytable as t1 ordery by t1.version DESC LIMIT 1; 
(DESC - For descending sort; LIMIT 1 chooses only the first row and 
DBMS usually does good optimization on seeing LIMIT). 
संबंधित मुद्दे