CTE और CTE के साथ (<column_names>) में क्या अंतर है?


11

जैसा कि MSDN पर कॉमन टेबल एक्सप्रेशंस का उपयोग करके दिखाया गया है , आप एक CTE को इस प्रकार परिभाषित कर सकते हैं:

WITH expression_name [ ( column_name [,...n] ) ]
AS
( CTE_query_definition )

और इसका उपयोग करें:

SELECT <column_list> FROM expression_name;

मान लीजिए कि मेरे पास 2 सीटीई हैं

with cte1 as(
select name from Table1
)

with cte2(name) as(
select name from Table1
)

एक क्वेरी दोनों सीटीई के लिए समान परिणाम उत्पन्न करता है क्योंकि आंतरिक क्वेरी समान है। इन दोनों के बीच एकमात्र अंतर यह है कि cte2 का स्तंभ नाम ( (name)) इसकी घोषणा में परिभाषित है।

जब मैं दोनों सीटीई निष्पादित करता हूं, तो मुझे निष्पादन योजना में कोई अंतर नहीं दिखता है।

मैं सिर्फ जानने के लिए उत्सुक हूं:

  • यदि मैं CTE परिभाषा में कोई कॉलम नाम निर्दिष्ट नहीं करता तो क्या फर्क पड़ता है?
  • CTE बनाते समय मुझे कॉलम के नाम क्यों नहीं निर्दिष्ट करने चाहिए?
  • क्या यह किसी भी संयोग से क्वेरी निष्पादन योजना को प्रभावित करता है? (जहां तक ​​मैंने देखा है, इससे कोई फर्क नहीं पड़ता।)

जवाबों:


25

आपके पास पहले से ही आपके किसी एक प्रश्न का उत्तर है।

में MSDN पेज, वहाँ एक लाइन सीधे अपने उद्धरण के बाद कि यह बताता है:

CTE के लिए मूल सिंटैक्स संरचना है:

अभिव्यक्ति_ने के साथ [(कॉलम_नाम [, ... एन])]

जैसा

(CTE_query_definition)

कॉलम नामों की सूची केवल वैकल्पिक है यदि सभी परिणामी स्तंभों के लिए अलग-अलग नाम क्वेरी परिभाषा में दिए गए हैं।

(महत्व दिया)

इसका अर्थ यह होगा कि आपको कुछ स्थितियों में कॉलम के नाम निर्दिष्ट करने होंगे:

  • यह काम करेगा:

    WITH [test_table] ([NoName], [CAST], [Function]) 
    AS
    (
        SELECT 
            1
          , CAST('1' AS CHAR(1))
          , dbo.CastToChar(1)
    )
    SELECT * FROM [test_table];
  • जैसा कि यह होगा:

    WITH [test_table]  
    AS
    (
        SELECT 
            1 as [NoName]
          , CAST('1' AS CHAR(1)) as [CAST]
          , dbo.CastToChar(1) as [Function]
    )
    SELECT * FROM [test_table];
  • लेकिन यह नहीं होगा क्योंकि इसमें कॉलम के अलग-अलग नाम नहीं हैं:

    WITH [test_table] 
    AS
    (
        SELECT 
            1
          , CAST('1' AS CHAR(1))
          , dbo.CastToChar(1)
    )
    SELECT * FROM [test_table];

1
अनिवार्य रूप से, स्तंभों के बिना संस्करण उसी तरह का है जैसे SQL के अतिरिक्त स्तंभ वाले संस्करण में क्वेरी से कॉलम नामों का "पता लगाना" होता है।
कुटुलुमाइक

10

वास्तविक रूप से, मैं WITH CTE (xxx) AS1 खंड के अंदर CTE के बजाय कॉलम का नाम देना पसंद करता हूं क्योंकि आप कभी भी अनजाने में स्तंभ सामग्री बनाम नामों को नहीं मिटाएंगे।

उदाहरण के लिए निम्न उदाहरण लें:

;WITH MyCTE (x, y)
AS 
(
    SELECT mt.y
         , mt.x
    FROM MySchema.MyTable mt
)
SELECT MyCTE.x
     , MyCTE.y
FROM MyCTE;

यह क्या प्रदर्शित करता है? यह की सामग्री से पता चलता yके शीर्षक के अंतर्गत स्तंभ x, और की सामग्री को xशीर्षक के अंतर्गत स्तंभ y

इस अहसास के साथ, मैं कभी भी(xxx) AS क्लॉज में कॉलम के नाम निर्दिष्ट नहीं करता , इसके बजाय मैं इसे इस तरह करता हूं:

;WITH MyCTE
AS 
(
    SELECT Alias1 = mt.y
         , Alias2 = mt.x
    FROM MySchema.MyTable mt
)
SELECT MyCTE.Alias1
     , MyCTE.Alias2
FROM MyCTE;

इससे स्तंभ की परिभाषाएं क्या हैं, इसके बारे में सभी संदेह दूर हो जाते हैं।

पूरी तरह से असंबंधित साइड-नोट पर; ऑब्जेक्ट नामों को संदर्भित करते समय हमेशा स्कीमा नाम निर्दिष्ट करें , और अपने बयानों को एक अर्ध-उपनिवेश के साथ समाप्त करें


7

अंततः प्रत्येक कॉलम को एक वैध नाम की आवश्यकता होती है और आप इसे दो तरीकों से निर्दिष्ट कर सकते हैं:

  1. स्तंभ सूची

    ;WITH cte (foo)
    AS
    ( select col from tab )
    select foo from cte;
  2. मूल स्तंभ नामों या उपनामों का उपयोग करना

    ;WITH cte
    AS
    ( select col from tab )
    select col from cte;

जब आप उपनाम और स्तंभ सूची दोनों करते हैं

  1. दोनों स्तंभ सूची और उपनाम

    ;WITH cte (foo, bar)
    AS
    ( select col1         -- not valid in outer Select
             col2 as colx -- not valid in outer Select
      from tab )
    select foo, bar from cte;

यह दृश्य या व्युत्पन्न तालिका की परिभाषा के समान है, जहां आप स्तंभ नामों की सूची भी निर्दिष्ट कर सकते हैं।

कॉलम सूची : जब आपके पास बहुत सी जटिल गणनाएँ होती हैं तो नाम को स्थान देना आसान होता है, क्योंकि वे स्रोत कोड के माध्यम से बिखरे हुए नहीं होते हैं। और यह आसान है अगर आपको एक पुनरावर्ती cte मिला है और आप # 3 में एक ही कॉलम के लिए दो अलग-अलग नाम निर्दिष्ट कर सकते हैं।

मूल नाम / उपनाम : आपको केवल एक उपनाम आवंटित करना है यदि आप एक गणना करते हैं या एक स्तंभ का नाम बदलना चाहते हैं / चाहिए


1
"स्पॉट करना आसान है" शायद थोड़ा व्यक्तिपरक है। मैं पंक्ति की शुरुआत में स्तंभ उपनामों को पसंद करता हूं, जैसे कि SomeAlias = SomeFunction(SomeColumn)प्रति पंक्ति केवल एक स्तंभ परिभाषा के साथ। यह कॉलम सूची के बाईं ओर नीचे एक साधारण स्कैन की अनुमति देता है, जिसे आप खोज रहे हैं।
मैक्स वर्नोन

1
@MaxVernon: यह सही है, और कई लाइनों में फैली गणनाओं के बीच रिक्त लाइनों को जोड़ने से भी मदद मिलती है। वास्तव में मैं ज्यादातर कॉलम सूची को छोड़ देता हूं, ...
dnoeth

2
मजेदार है कि आपने विचारों का उल्लेख किया। मैंने किसी दृश्य को परिभाषित करते समय दृश्य नाम के बाद कॉलम सूची का उपयोग कभी नहीं किया है, जैसे कि CREATE VIEW SomeView (ColA, ColB, …) AS …। अब जब कि आप इसे लाए हैं, तो मैं इस तरह के परिदृश्यों के बारे में सोच रहा हूं CREATE VIEW MyView (G) AS WITH cte (C) AS (SELECT A AS B FROM MyTable) SELECT E AS F FROM (SELECT C AS D FROM cte) AS s (E);- क्या होगा जो डिबग करने के लिए एक खुशी है!
एंड्री एम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.