2011-09-05 6 views
6

यह सवाल कुछ दूसरी बार पूछा गया था, लेकिन मैं अभी भी सही जवाब या उचित तरीका यह है सुलझाने के लिए प्रबंधन नहीं किया:कैसे घोंसला करने के लिए CTE ठीक से

...

;WITH CTE AS 
(
    SELECT * FROM ... 
) 
SELECT *, [dbo].[udf_BetaInv](A, B, C, D) AS 'Loss' 
FROM CTE 
WHERE (Loss >= @MinRetention) 

यह काम नहीं करता है और मैं संग्रहित प्रक्रिया नहीं बना सकता, स्पष्ट रूप से मैं कहां में नुकसान का उपयोग नहीं कर सकता क्योंकि उस दायरे में मौजूद नहीं है।

मैं एक CTE उपयोग करने के लिए यह एक रैप करने के लिए तो मैं बाहरी एक पर कहां रख सकते हैं चाहते हैं लेकिन नहीं काम करने के लिए नहीं लगता है, करने की कोशिश की इस:

;WITH CTE AS 
(
    SELECT * FROM ... 
) 
SELECT *, [dbo].[udf_BetaInv(A, B, C, D) AS 'Loss' 
FROM CTE, 
RESULTS AS 
(SELECT * FROM CTE) 
    SELECT * 
    FROM RESULTS 
    WHERE (Loss >= @MinRetention) 

लेकिन यह एसक्यूएल में संकलन नहीं है सर्वर, मुझे एक त्रुटि मिलती है कि '(' उपरोक्त कई पंक्तियों को गलत जगह पर रखता है लेकिन अगर मैं दूसरा सीटीई हटा देता हूं तो यह करने के लिए कुछ भी नहीं है।

मैं केवल कोड डुप्लिकेशन से बचना चाहता हूं, मेरी कॉल नहीं करना चाहता [ udf_BetaInv] चयन में दो बार और जहां भी।

+0

क्या आपका मतलब '[हानि]' (एक कॉलम नाम) '' लॉस '(एक स्ट्रिंग) नहीं है? सुनिश्चित नहीं है कि अगर त्रुटि उत्पन्न होगी, हालांकि – Rup

उत्तर

13

आपके पास इंटरमीडिएट SELECT है जो आपके पास नहीं होना चाहिए। यह काम करना चाहिए:

;WITH CTE AS 
(
    SELECT * FROM ... 
), 
RESULTS AS 
(
    SELECT *, [dbo].[udf_BetaInv(A, B, C, D) AS 'Loss' 
    FROM CTE 
) 
SELECT * 
FROM RESULTS 
WHERE (Loss >= @MinRetention) 
+0

धन्यवाद, अच्छा काम भी करता है, मुझे नहीं पता था कि मेरे पास बहुत से चयन हैं: डी –

+1

यह आवश्यक नहीं है लेकिन स्तंभों को स्पष्ट रूप से नाम देने के लिए एक अच्छा प्रैटिस आपके सीटीई नाम में, यानी .... परिणाम ([सीटीई से कॉलम नाम], नुकसान) .... आप बाद में धन्यवाद देंगे: पी। – deutschZuid

7

स्पष्ट रूप से probl पहली क्वेरी के साथ यह है कि 'लॉस' सिर्फ एक कॉलम उपनाम है और इसका उपयोग WHERE खंड में नहीं किया जा सकता है। आप सही हैं कि एक सीटीई में इसका उपयोग अभिव्यक्ति को डुप्लिकेट करने से बचें। यहां बताया गया है कि आप यह कैसे करेंगे;

WITH CTE AS 
( 
    SELECT * FROM ... 
), 
CteWithLoss AS ( 
    SELECT *, [dbo].[udf_BetaInv](A, B, C, D) AS 'Loss' 
    FROM CTE 
) 
SELECT * 
FROM CteWithLoss 
WHERE (Loss >= @MinRetention); 

एक तरफ ध्यान दें पर: यदि आप ;WITH के साथ अपने CTE परिभाषाओं शुरू करने की आदत को तोड़ने और बजाय एक सेमी-कोलन के साथ अपने सभी SQL कथन समाप्त होने के आदत में प्राप्त कर सकते हैं देखें। यह अधिक पठनीय और बेहतर अभ्यास है।

+0

धन्यवाद अब पूरी तरह से काम करता है :) –

+0

मुझे पहले सीटीई की आवश्यकता है, क्वेरी इस पर निर्भर करती है। इसे करने का कोई तरीका है? – Akbari

+0

प्लस वन "सीटीई परिभाषाओं को शुरू करने की आदत को तोड़ने के लिए;" – DaveBoltman

0

नीचे नेस्टेड CTE का उदाहरण है।

with cte_data as 
(
    Select * from [HumanResources].[Department] 
),cte_data1 as 
(
    Select * from cte_data 
) 

select * from cte_data1 
+0

यह घोंसला नहीं है, बस एक और सीटीई पहले के संदर्भ में संदर्भित है। – DaveBoltman

+0

यह डेव नेस्टेड है। वास्तव में यह एक घोंसला वाले सीटीई की परिभाषा काफी सुंदर है। क्या आप रिकर्सिव सीटीई के बारे में सोच रहे थे? यह एक बिल्कुल नया बॉल गेम है और बहुत मजेदार है लेकिन ओपी ने अनुरोध नहीं किया। –

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