2012-10-22 15 views
5

अगर मैं की तरहयदि क्वेरी में कई स्थानों पर एक गैर-सहसंबंधित सबक्वायरी दोहराई जाती है, तो इसे कैश किया जा सकता है और परिणाम पुन: उपयोग किया जा सकता है?

SELECT date_trunc('day', assigndate)e, 
     count(CASE WHEN a.assigneeid = 65548 
      AND a.assigneeid IN 
       (SELECT userid 
       FROM groupmembers 
       WHERE groupid = 65553) THEN 1 ELSE NULL END) assigned, 
     count(CASE WHEN a.assigneeid = 65548 
      AND a.completedtime IS NOT NULL 
      AND a.assigneeid IN 
       (SELECT userid 
       FROM groupmembers 
       WHERE groupid = 65553) THEN 1 ELSE NULL END) completed 
FROM ASSIGNMENT a 
WHERE assigndate > CURRENT_TIMESTAMP - interval '20 days' 
GROUP BY date_trunc('day',assigndate); 
एक प्रश्न

प्रश्न में सबक्वेरी

SELECT userid 
       FROM groupmembers 
       WHERE groupid = 65553 

तब से सबक्वेरी माता पिता प्रश्न के not co-related है, यह सिर्फ एक बार निष्पादित किया जाएगा और कैश की गई परिणाम होगा उपयोग किया गया। लेकिन चूंकि सबक्वायरी क्वेरी में 2 स्थानों पर मौजूद है, तो SQL plan के अनुसार, इसका मूल्यांकन दो बार का मूल्यांकन किया जाता है। क्या उस सबक्वायरी के परिणाम cache पर कोई रास्ता है और दोनों स्थानों पर इसका उपयोग करें?

सबक्वेरी एक में शामिल होने के रूप में कोई भी क्षेत्र है जिस पर शामिल होने के लिए है (और यह बिना शर्त नहीं किया जा सकता शामिल हो, के रूप में गिनती गलत तो हो जाएगा)

+1

आपके पास एक अनावश्यक अभिव्यक्ति दिखाई देती है। "A.assigneeid = 65548" और "a.assigneeid में (subquery)" कहने वाला कोई खंड नहीं है - वे या तो दोनों सत्य हैं या दोनों झूठे हैं। – adhocgeek

+0

यह केवल प्रदर्शन कारणों के लिए था (खराब तर्क, हालांकि!) – Daud

उत्तर

10

आप एक का उपयोग कर सकते करने के लिए परिवर्तित नहीं किया जा सकता आम तालिका एक्सप्रेस (WITH)

with cte as 
(
    SELECT userid FROM groupmembers WHERE groupid = 65553 
) 
SELECT 
    date_trunc('day', assigndate)e, 
    count(CASE WHEN a.assigneeid = 65548 AND a.assigneeid IN 
      (SELECT userid from cte) then 1 else null end) assigned, 
... 
+0

इसका एक और बदलाव अस्थायी तालिका का उपयोग करना और इसमें शामिल होना होगा ताकि आप केवल उस दिए गए कथन को निष्पादित कर सकें। – Kuberchaun

+0

SQL सर्वर में, यह * गारंटी नहीं देता है कि सबक्वायरी केवल एक बार चलती है। क्या पोस्टग्रेस इसकी गारंटी देता है? –

+0

@JustBob - असाइनमेंट टेबल के साथ उस अस्थायी तालिका में शामिल होने का कोई तरीका नहीं होगा, और यूनियन गलत होगा, गिनती गलत की गणना – Daud

1

आप क्वेरी को फिर से लिखने चाहिए सबक्वेरी खत्म करने के लिए:

SELECT date_trunc('day', assigndate)e, 
     sum(CASE WHEN a.assigneeid = 65548 and gm.userid is not null then 1 else 0 
      end) as assigned, 
     sum(CASE WHEN a.assigneeid = 65548 and a.completedtime IS NOT NULL and gm.userid is not null 
       then 1 else 0 
      end) as completed 
FROM ASSIGNMENT a left outer join 
    (select distinct userid 
     from groupmembers 
     where groupid = 65553 
    ) gm 
    on a.assigneeid = gm.userid 
WHERE assigndate > CURRENT_TIMESTAMP - interval '20 days' 
GROUP BY date_trunc('day',assigndate) 
order by 1 

सामान्य तौर पर, मुझे लगता है कि यह करने के लिए की अच्छी आदत है FROM (या WITH) खंड में पी तालिका संदर्भ। SELECT खंड में सबक्वायरी के तर्क का पालन करना मुश्किल हो सकता है। इस मामले में, सबक्वायरी इतनी कमजोर हैं कि वे व्यावहारिक रूप से एक कथन में शामिल होने के लिए भीख मांग रहे हैं।

+0

समानता को इंगित करने के लिए धन्यवाद, लेकिन वास्तविक परिदृश्य में, दृष्टिकोण के साथ एक गिनती खंड भी है। इस प्रकार, मैं असाइनिड पर शामिल नहीं हो सकता – Daud

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