Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

रैंकिंग कार्यों के साथ पुनरावर्ती सीटीई

संपादित करें

जब आप पुनरावर्तन के संबंध में CTE दस्तावेज़ पढ़ते हैं, तो आप देखेंगे कि इसकी कुछ सीमाएँ हैं, जैसे कि उपश्रेणियों का उपयोग करने में सक्षम नहीं होना, समूह-दर, शीर्ष। इन सभी में कई पंक्तियाँ शामिल हैं। सीमित परीक्षण से, और निष्पादन योजना की जाँच के साथ-साथ इस क्वेरी के परीक्षण से

with cte as (
  select 1 a, 1 b union all select 1, 2 union all select 1, 3 union all select 2, 4
)
, rcte (a, b, c, d) as (
  select a, b, cast(0 as int), 1 
  from cte
  union all
  select r.a, cte.b, cast(ROW_NUMBER() over (order by r.b) as int), r.d+1
  from rcte r inner join cte on cte.a=r.a
  where r.d < 2
)
select * 
from rcte
where d=2
order by a, b

मैं केवल निष्कर्ष निकाल सकता हूं:

  1. Row_Number() एक सीटीई में काम करता है, जब एक बहु-पंक्ति परिणाम सेट बनाने के लिए अन्य तालिकाओं को जोड़ा जाता है
  2. नंबरिंग के परिणामों से, यह स्पष्ट है कि सीटीई को एक पंक्ति में सभी पुनरावृत्तियों के माध्यम से संसाधित किया जाता है, बहु-पंक्ति-दर-मल्टीरो के बजाय पंक्ति-दर-पंक्ति, भले ही यह सभी पंक्तियों को एक साथ पुनरावृत्त करता प्रतीत होता है। यह समझाता है कि रिकर्सिव सीटीई के लिए बहु-पंक्ति संचालन पर लागू होने वाले किसी भी फ़ंक्शन की अनुमति क्यों नहीं है।

हालांकि मैं इस निष्कर्ष पर आसानी से पहुंच गया, किसी ने स्पष्ट रूप से इसे कष्टदायी विस्तार से समझाएं केवल 17 महीने पहले...

दूसरे शब्दों में, यह SQL सर्वर के कार्यान्वयन . की प्रकृति है पुनरावर्ती CTE, इसलिए विंडोिंग फ़ंक्शन आपकी अपेक्षा के अनुरूप काम नहीं करेंगे।

दूसरों के लाभ के लिए, आउटपुट है:
a           b           c           d
----------- ----------- ----------- -----------
1           1           1           2
1           2           1           2
2           3           1           2
2           4           1           2

जबकि आप उम्मीद कर रहे हैं कि c में 1,1,1,1 के बजाय 1,2,1,2 होंगे। यह निश्चित रूप से ऐसा लगता है कि यह एक बग हो सकता है, क्योंकि यह कहने के लिए कोई दस्तावेज नहीं है कि विंडोिंग फ़ंक्शन को CTE के पुनरावर्ती भाग में काम नहीं करना चाहिए।

नोट:row_number() बिगिंट लौटाता है, इसलिए आप केवल एंकर (सी) को बिगिंट के रूप में डाल सकते हैं।

चूंकि प्रत्येक पुनरावृत्ति d बढ़ाता है, आप विंडोिंग को बाहर कर सकते हैं।

with cte as (
  select 1 a, 1 b union all select 1, 2 union all select 2, 3 union all select 2, 4
)
, rcte (a, b, d) as (
  select a, b, 1 
  from cte
  union all
  select a, b, d+1
  from rcte
  where d < 2
)
select a,b, ROW_NUMBER() over (partition by a,d order by b) c,d
from rcte
--where d=2
order by d, a, b

संपादित करें - अंतर्दृष्टि

जवाब देते समय /ए> , मैंने रिकर्सिव सीटीई के साथ कुछ और खेला। यदि आप इसे अंतिम ORDER BY के बिना चलाते हैं, तो आप देख सकते हैं कि SQL सर्वर रिकर्सन के पास कैसे आ रहा है। यह दिलचस्प है कि यह इस मामले में पीछे की ओर जाता है, फिर प्रत्येक पंक्ति पर पूरी गहराई-पहली रिकर्सन करता है।

नमूना तालिका

create table Testdata(SomeID int, OtherID int, Data varchar(max))
insert Testdata select 1, 9, '18,20,22,alpha,beta,gamma,delta'
insert Testdata select 2, 6, ''
insert Testdata select 3, 8, '11,12,.'
insert Testdata select 4, 7, '13,19,20,66,12,232,1232,12312,1312,abc,def'
insert Testdata select 5, 8, '17,19'

एक पुनरावर्ती क्वेरी

;with tmp(SomeID, OtherID, DataItem, Data) as (
select SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
    STUFF(Data, 1, CHARINDEX(',',Data+','), '')
from Testdata
union all
select SomeID, OtherID, LEFT(Data, CHARINDEX(',',Data+',')-1),
    STUFF(Data, 1, CHARINDEX(',',Data+','), '')
from tmp
where Data > ''
)
select SomeID, OtherID, DataItem, Data
from tmp
-- order by SomeID

आउटपुट एक पुनरावृत्ति में संसाधित सीटीई एंकर दिखाता है, फिर किसी भी कारण से अन्य पंक्तियों को संसाधित करने से पहले एंकर सेट में प्रत्येक पंक्ति को पूरा (गहराई-प्रथम) करने के लिए पुन:प्रस्तुत किया जाता है।

फिर भी इसके अजीबोगरीब उपयोग हैं, जैसे यह उत्तर दिखाता है




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पैरामीटरयुक्त क्वेरी उस पैरामीटर की अपेक्षा करती है जो आपूर्ति नहीं की गई थी

  2. SQL सर्वर में वर्तमान सत्र के लिए भाषा बदलें

  3. SQL सर्वर को समझना हमेशा एन्क्रिप्टेड

  4. SQL सर्वर:CREATE DATABASE में पैरामीटर का उपयोग करें

  5. 2 SQL सर्वर डेटाबेस मर्ज करें