कई स्तरों के पदानुक्रम बनाएं जहां प्रत्येक नोड में बच्चों की यादृच्छिक संख्या होती है


16

मुझे कुछ परीक्षण डेटा बनाने की आवश्यकता है जिसमें एक पदानुक्रम शामिल है। मैं इसे आसान बना सकता हूं और कुछ कर सकता हूं CROSS JOIN, लेकिन इससे मुझे एक ऐसा ढांचा मिलेगा जो पूरी तरह से एक समान / बिना किसी बदलाव के है। यह न केवल सुस्त लगता है, बल्कि परीक्षण डेटा में भिन्नता की कमी कभी-कभी ऐसी समस्याओं का सामना करती है जो अन्यथा मिल जाती हैं। इसलिए, मैं एक गैर-समान पदानुक्रम उत्पन्न करना चाहता हूं जो इन नियमों का पालन करता है:

  • 3 स्तर गहरा
    • स्तर 1 बेतरतीब ढंग से 5 - 20 नोड्स है
    • स्तर 2 1 - 10 नोड है, स्तर 1 के प्रत्येक नोड के लिए यादृच्छिक
    • स्तर 3 1 - 5 नोड्स है, स्तर 2 के प्रत्येक नोड के लिए यादृच्छिक
  • सभी शाखाएँ 3 स्तर गहरी होंगी। इस बिंदु पर गहराई में एकरूपता ठीक है।
  • किसी भी स्तर पर बाल नोड्स के नाम पर ओवरलैप किया जा सकता है (यानी बच्चे नोड्स के नाम समान स्तर पर सभी नोड्स में अद्वितीय होने की आवश्यकता नहीं है)।
  • "यादृच्छिक" शब्द को यहां छद्म यादृच्छिक के रूप में परिभाषित किया गया है, न कि विशिष्ट रूप से यादृच्छिक । यह उल्लेख करने की आवश्यकता है क्योंकि "यादृच्छिक" शब्द का उपयोग अक्सर "किसी दिए गए सेट के यादृच्छिक क्रम का अर्थ होता है जो डुप्लिकेट का उत्पादन नहीं करता है"। मुझे लगता है कि यादृच्छिक = यादृच्छिक स्वीकार करते हैं और यदि स्तर 1 के प्रत्येक नोड में बच्चों की संख्या केवल 4, 7, और 8 है, यहां तक ​​कि स्तर 1 पर 20 नोड्स हैं, जिनमें से प्रत्येक नोड में 1 - 10 बच्चों का संभावित प्रसार है, फिर वह ठीक है, क्योंकि वह यादृच्छिक है।
  • भले ही यह नेस्टेड WHILEछोरों के साथ काफी आसानी से किया जा सकता है , वरीयता एक सेट-आधारित दृष्टिकोण खोजने के लिए है। सामान्यतया, परीक्षण डेटा उत्पन्न करने के लिए दक्षता की आवश्यकताएं नहीं होती हैं जो उत्पादन कोड के लिए होती हैं, लेकिन सेट-आधारित दृष्टिकोण के लिए शूटिंग संभवतः अधिक शैक्षिक होगी और भविष्य में समस्याओं के लिए सेट-आधारित दृष्टिकोण खोजने में मदद करेगी। इसलिए WHILEलूप्स को इंकार नहीं किया जाता है, लेकिन इसका उपयोग केवल तभी किया जा सकता है जब कोई सेट-आधारित दृष्टिकोण संभव न हो।
  • सेट-आधारित = आदर्श रूप से CTE, APPLYs इत्यादि की परवाह किए बिना एक एकल क्वेरी, इसलिए मौजूदा या इनलाइन नंबर तालिका का उपयोग करना ठीक है। WHILE / CURSOR / प्रक्रियात्मक दृष्टिकोण का उपयोग करने से काम नहीं चलेगा। मुझे लगता है कि टेंपरेचर टेबल या टेबल वैरिएबल में डेटा के स्टेजिंग फाइन ठीक हैं, बस इतनी देर तक जब तक ऑपरेशंस सब सेट-बेस्ड न हों, कोई लूप न हो। हालाँकि, यह कहा जा रहा है, एक एकल-क्वेरी दृष्टिकोण संभवतः कई प्रश्नों पर पसंदीदा होगा, जब तक कि यह नहीं दिखाया जा सकता है कि बहु-क्वेरी दृष्टिकोण वास्तव में बेहतर है। कृपया यह भी ध्यान रखें कि "बेहतर" का गठन आमतौर पर व्यक्तिपरक होता है ;-)। कृपया यह भी ध्यान रखें कि पूर्व वाक्य में "आम तौर पर" का उपयोग भी व्यक्तिपरक है।
  • SQL सर्वर का कोई भी संस्करण और संस्करण (2005 और नया, मुझे लगता है) करेगा।
  • केवल शुद्ध टी-एसक्यूएल: उस मूर्ख SQLCLR सामान में से कोई भी नहीं !! कम से कम डेटा पैदा करने के मामले में। निर्देशिकाओं और फ़ाइलों को बनाना SQLCLR का उपयोग करके किया जाएगा। लेकिन यहां मैं सिर्फ बनाने के मूल्यों पर ध्यान केंद्रित कर रहा हूं।
  • T-SQL मल्टी-स्टेटमेंट TVF को प्रक्रियात्मक माना जाता है, सेट-आधारित नहीं, भले ही बाहर पर वे एक सेट में प्रक्रियात्मक दृष्टिकोण को मुखौटा करते हैं। ऐसे समय होते हैं जब यह बिल्कुल उपयुक्त होता है। यह उन समयों में से एक नहीं है। उन्हीं लाइनों के साथ, टी-एसक्यूएल स्केलेर फ़ंक्शन को भी अनुमति नहीं है, न केवल क्योंकि वे भी प्रक्रियात्मक हैं, लेकिन क्वेरी ऑप्टिमाइज़र कभी-कभी उनके मूल्य को कैश करता है और इसे दोहराता है जैसे कि आउटपुट अपेक्षित नहीं है।
  • T-SQL इनलाइन TVFs (उर्फ iTVFs) ओके-डॉक हैं क्योंकि वे सेट-आधारित हैं, और प्रभावी रूप से उपयोग करने के समान हैं [ CROSS | OUTER ] APPLY, जो कि ठीक होने के रूप में ऊपर कहा गया था।
  • क्वेरी (ies) के बार-बार निष्पादित होने से पहले के रन से ज्यादातर अलग परिणाम उत्पन्न होने चाहिए।
  • क्लैरिफिकेशन अपडेट 1: अंतिम परिणाम सेट को लेवल 1 पर शुरू होने वाले पूर्ण पथ वाले प्रत्येक लेवल नोड 3 के लिए एक पंक्ति के रूप में व्यक्त किया जाना चाहिए। इसका मतलब यह है कि Level1 और Level2 मान आवश्यक रूप से एक या अधिक पंक्तियों में दोहराएंगे, सिवाय इसके कि केवल एकल Level3 नोड वाले एकल Level2 नोड होने के मामलों में।
  • स्पष्टीकरण अद्यतन 2: नाम या लेबल वाले प्रत्येक नोड के लिए एक बहुत मजबूत प्राथमिकता है, और न केवल एक संख्या है। यह परिणामी परीक्षण डेटा को अधिक सार्थक और यथार्थवादी होने देगा।

मुझे यकीन नहीं है कि यह अतिरिक्त जानकारी मायने रखती है, लेकिन सिर्फ अगर यह कुछ संदर्भ में मदद करता है, तो परीक्षण डेटा इस पर मेरे जवाब से संबंधित है:

XML फ़ाइलों को SQL सर्वर 2012 में आयात करें

जबकि इस बिंदु पर प्रासंगिक नहीं है, इस पदानुक्रम को उत्पन्न करने का अंतिम लक्ष्य पुनरावर्ती फ़ाइल सिस्टम विधियों का परीक्षण करने के लिए एक निर्देशिका संरचना बनाना है। स्तर 1 और 2 निर्देशिकाएं होंगी, और स्तर 3 फ़ाइल नाम होने पर समाप्त हो जाएगा। मैंने चारों ओर (गोगल्स के माध्यम से) खोज की है और एक यादृच्छिक पदानुक्रम उत्पन्न करने के लिए केवल एक संदर्भ पाया है:

लिनक्स: यादृच्छिक निर्देशिका / फ़ाइल पदानुक्रम बनाएँ

यह प्रश्न (स्टैकऑवरफ्लो पर) वास्तव में वांछित परिणाम के संदर्भ में काफी करीब है क्योंकि यह परीक्षण के लिए एक निर्देशिका संरचना बनाना चाहता है। लेकिन यह प्रश्न (और उत्तर) लिनक्स / यूनिक्स शेल स्क्रिप्टिंग पर केंद्रित है और इतनी अधिक सेट-आधारित दुनिया नहीं है जिसमें हम रहते हैं।

अब, मुझे पता है कि यादृच्छिक डेटा कैसे उत्पन्न किया जाता है, और फ़ाइलों की सामग्री बनाने के लिए पहले से ही ऐसा कर रहा हूं ताकि वे भी विविधताएं दिखा सकें। यहां मुश्किल हिस्सा यह है कि प्रत्येक सेट के भीतर तत्वों की संख्या यादृच्छिक है, विशेष क्षेत्र नहीं। और , प्रत्येक नोड के भीतर तत्वों की संख्या को उसी स्तर पर अन्य नोड्स से यादृच्छिक होना चाहिए।

उदाहरण पदानुक्रम

     Level 1
              Level 3
|---- A
|     |-- 1
|     |   |--- I
|     |
|     |-- 2
|         |--- III
|         |--- VI
|         |--- VII
|         |--- IX
|
|---- B
|     |-- 87
|         |--- AAA
|         |--- DDD
|
|---- C
      |-- ASDF
      |   |--- 11
      |   |--- 22
      |   |--- 33
      |
      |-- QWERTY
      |   |--- beft
      |
      |-- ROYGBP
          |--- Poi
          |--- Moi
          |--- Soy
          |--- Joy
          |--- Roy

उदाहरण परिणाम सेट करें ऊपर पदानुक्रम का वर्णन करते हुए

Level 1    Level 2    Level 3
A          1          I
A          2          III
A          2          VI
A          2          VII
A          2          IX
B          87         AAA
B          87         DDD
C          ASDF       11
C          ASDF       22
C          ASDF       33
C          QWERTY     beft
C          ROYGBP     Poi
C          ROYGBP     Moi
C          ROYGBP     Soy
C          ROYGBP     Joy
C          ROYGBP     Roy

जवाबों:


9

( ओपी का नोट: पसंदीदा समाधान 4 / अंतिम कोड ब्लॉक है)

XML मुझे यहाँ उपयोग करने के लिए डेटा संरचना का स्पष्ट विकल्प लगता है।

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)

select top(5 + abs(checksum(newid())) % 15)
  N1.N as '@Value',
  (
  select top(1 + abs(checksum(newid())) % 10)
    N2.N as '@Value',
    (
    select top(1 + abs(checksum(newid())) % 5)
      N3.N as '@Value'
    from N as N3
    where N2.N > 0
    for xml path('Level3'), type
    )
  from N as N2
  where N1.N > 0
  for xml path('Level2'), type
  )
from N as N1
for xml path('Level1'), root('Root');

SQL सर्वर बनाने के top()लिए प्रत्येक नोड के लिए अलग-अलग मानों का उपयोग करने की चाल उप-प्रश्नों को सहसंबद्ध बनाने के लिए है। N1.N > 0और N2.N > 0

XML को समतल करना:

declare @X xml;

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)
select @X  = (
             select top(5 + abs(checksum(newid())) % 15)
               N1.N as '@Value',
               (
               select top(1 + abs(checksum(newid())) % 10)
                 N2.N as '@Value',
                 (
                 select top(1 + abs(checksum(newid())) % 5)
                   N3.N as '@Value'
                 from N as N3
                 where N2.N > 0
                 for xml path('Level3'), type
                 )
               from N as N2
               where N1.N > 0
               for xml path('Level2'), type
               )
             from N as N1
             for xml path('Level1')
             );


select L1.X.value('@Value', 'varchar(10)')+'\'+
       L2.X.value('@Value', 'varchar(10)')+'\'+
       L3.X.value('@Value', 'varchar(10)')
from @X.nodes('/Level1') as L1(X)
  cross apply L1.X.nodes('Level2') as L2(X)
  cross apply L2.X.nodes('Level3') as L3(X);

और एक संस्करण पूरी तरह से XML से शून्य है।

with N as
(
  select T.N
  from (values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),
              (12),(13),(14),(15),(16),(17),(18),(19),(20)) as T(N)
)
select cast(N1.N as varchar(10))+'\'+
       cast(N2.N as varchar(10))+'\'+
       cast(N3.N as varchar(10))
from (
     select top(5 + abs(checksum(newid())) % 15)
       N.N
     from N
     ) as N1
  cross apply
     (
     select top(1 + abs(checksum(newid())) % 10)
       N.N
     from N
     where N1.N > 0
     ) as N2
  cross apply
     (
     select top(1 + abs(checksum(newid())) % 5)
       N.N
     from N
     where N2.N > 0
     ) as N3;

सहसंबंध N1.N > 0और N2.N > 0अभी भी महत्वपूर्ण है।

केवल पूर्णांकों के बजाय 20 नामों वाली तालिका का उपयोग करने वाला संस्करण।

declare @Elements table
(
  Name nvarchar(50) not null
);

insert into @Elements(Name)
select top(20) C.name 
from sys.columns as C
group by C.name;

select N1.Name + N'\' + N2.Name + N'\' + N3.Name
from (
     select top(5 + abs(checksum(newid())) % 15)
       E.Name
     from @Elements as E
     ) as N1
  cross apply
     (
     select top(1 + abs(checksum(newid())) % 10)
       E.Name
     from @Elements as E
     where N1.Name > ''
     ) as N2
  cross apply
     (
     select top(1 + abs(checksum(newid())) % 5)
       E.Name
     from @Elements as E
     where N2.Name > ''
     ) as N3;

1
मुझे नया वर्जन बेहतर लगता है। यह लगभग वही बात है जो मैं अपने पहले प्रयास में लेकर आया था लेकिन किसी कारण से मैं TOP(n)2 CROSS APPLYएस में सही तरीके से काम नहीं कर पाया । निश्चित रूप से जब मैं कुछ और काम कर रहा था, तो मुझे यकीन नहीं था कि मैंने अलग-अलग / गलत तरीके से किया था। मैं इसे जल्द ही पोस्ट करूंगा, अब जब आपने यह अपडेट प्रदान किया है। और मैंने अपनी अधिकांश टिप्पणियों को ऊपर साफ किया है।
सोलोमन रटज़की

मैंने अभी अपना संस्करण पोस्ट किया है। मुख्य अंतर इस प्रकार हैं: 1) चूंकि मुझे काम करने के लिए TOP (n) नहीं मिल रहा है, मैं nWHERE की स्थिति के माध्यम से तत्व प्राप्त कर रहा हूं , और 2) मेरे पास nameघटक है जो यादृच्छिक निर्देशिका और / या फ़ाइल नामों की तुलना में अधिक नियंत्रित है। ।
सोलोमन रटज़की

इतने लंबे समय तक दूर रहने के लिए क्षमा करें, लेकिन मैं व्यस्त हूं। फिर भी, मैं इस बारे में सोच रहा हूं और अपने उत्तर और आपके गैर-XML संस्करण के बीच निर्णय नहीं कर सकता। मुझे आपकी सादगी और लचीलापन पसंद है, लेकिन एक फ़ोल्डर संरचना बनाने के लिए नामों को वापस करने की क्षमता की आवश्यकता है, जो मेरा है। तब मुझे एहसास हुआ कि मेरे पास व्लाद अद्यतन करने के लिए एक लुकअप टेबल है और आदर्श आउटपुट देने के लिए इसमें शामिल हों। इसलिए, यदि पूछना अनुचित नहीं है, तो क्या आप उसी अद्यतन को शामिल करने के लिए आपको अपडेट कर सकते हैं? तब सभी 3 उत्तर समान आउटपुट (सभी 3 की तुलना के लिए आदर्श) देंगे, और मैं आपका स्वीकार करूंगा। क्या वह ठीक है?
सोलोमन रटज़की

1
@srutzky मैंने उत्तर को अपडेट कर दिया है। कुछ समय पहले था इसलिए आशा थी कि मैं इसे सही कर पाऊंगा और आपको कहां ढूंढना होगा। आप निश्चित रूप @Elemetsसे चुनने के लिए प्रत्येक स्तर के लिए नामों का एक अलग सेट प्राप्त करने के लिए एक स्तर स्तंभ जोड़ सकते हैं।
मिकेल एरिकसन

1
@srutzky कोई चिंता नहीं। मुझे खुशी है कि उत्तर आपके लिए मददगार था।
मिकेल एरिकसन

6

यह दिलचस्प था।

मेरा उद्देश्य एक उचित रूप से जुड़े पदानुक्रमित संरचना में प्रत्येक स्तर के साथ बाल पंक्तियों की यादृच्छिक संख्या के साथ स्तरों की संख्या उत्पन्न करना था। एक बार यह संरचना तैयार हो जाने के बाद इसमें फ़ाइल और फ़ोल्डर नामों की तरह अतिरिक्त जानकारी जोड़ना आसान होता है।

इसलिए, मैं एक पेड़ के भंडारण के लिए एक क्लासिक तालिका तैयार करना चाहता था:

ID int NOT NULL
ParentID int NULL
Lvl int NOT NULL

चूंकि हम पुनरावृत्ति से निपट रहे हैं, पुनरावर्ती CTE एक स्वाभाविक पसंद है।

मुझे अंक तालिका की आवश्यकता होगी । तालिका में संख्याएँ 1 से शुरू होनी चाहिए। तालिका में कम से कम 20 संख्याएँ होनी चाहिए MAX(LvlMax):।

CREATE TABLE [dbo].[Numbers](
    [Number] [int] NOT NULL,
CONSTRAINT [PK_Numbers] PRIMARY KEY CLUSTERED 
(
    [Number] ASC
));

INSERT INTO Numbers(Number)
SELECT TOP(1000)
    ROW_NUMBER() OVER(ORDER BY S.object_id)  AS Number
FROM
    sys.all_objects AS S
ORDER BY Number;

डेटा जनरेशन के लिए पैरामीटर एक तालिका में संग्रहीत किए जाने चाहिए:

DECLARE @Intervals TABLE (Lvl int, LvlMin int, LvlMax int);
INSERT INTO @Intervals (Lvl, LvlMin, LvlMax) VALUES
(1, 5, 20),
(2, 1, 10),
(3, 1, 5);

ध्यान दें, क्वेरी बहुत ही लचीली है और सभी मापदंडों को एक ही स्थान पर अलग किया गया है। यदि आवश्यक हो तो आप और अधिक स्तर जोड़ सकते हैं, बस मापदंडों की एक अतिरिक्त पंक्ति जोड़ सकते हैं।

ऐसी गतिशील पीढ़ी को संभव बनाने के लिए मुझे अगले स्तर के लिए पंक्तियों की यादृच्छिक संख्या को याद रखना था, इसलिए मेरे पास एक अतिरिक्त कॉलम है ChildRowCount

उत्पन्न अद्वितीय IDs भी कुछ हद तक मुश्किल है। मैं हार्ड-कोडित 100 चाइल्ड रो की 1 पेरेंट पंक्ति की सीमा की गारंटी देता IDsहूं कि वह दोहराए नहीं। यह वह है जो POWER(100, CTE.Lvl)इसके बारे में है। परिणामस्वरूप बड़े अंतराल होते हैं IDs। यह संख्या एक हो सकती है MAX(LvlMax), लेकिन मैंने सरलता के लिए क्वेरी में निरंतर 100 डाला। स्तरों की संख्या हार्ड-कोडेड नहीं है, लेकिन इसके द्वारा निर्धारित की जाती है @Intervals

यह सूत्र

CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5

रेंज में एक यादृच्छिक फ्लोटिंग पॉइंट नंबर उत्पन्न करता है [0..1), जिसे बाद में आवश्यक अंतराल तक बढ़ाया जाता है।

क्वेरी तर्क सरल है। यह पुनरावर्ती है। पहला चरण पहले स्तर की पंक्तियों का एक सेट उत्पन्न करता है। पंक्तियों की संख्या यादृच्छिक संख्या से निर्धारित होती है TOP। साथ ही, प्रत्येक पंक्ति के लिए अलग-अलग यादृच्छिक संख्या में चाइल्ड रो को स्टोर किया जाता है ChildRowCount

रिकर्सिव पार्ट CROSS APPLYप्रत्येक पेरेंट पंक्ति में दिए गए चाइल्ड रो की संख्या उत्पन्न करने के लिए उपयोग करता है। मुझे WHERE Numbers.Number <= CTE.ChildRowCountइसके बजाय उपयोग करना था TOP(CTE.ChildRowCount), क्योंकि TOPCTE के पुनरावर्ती भाग में अनुमति नहीं है। SQL सर्वर की इस सीमा के बारे में पहले नहीं पता था।

WHERE CTE.ChildRowCount IS NOT NULL पुनरावृत्ति को रोकता है।

एसक्यूएल फिडल

WITH
CTE
AS
(
    SELECT 
        TOP(CAST(
            (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
            (
                1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = 1)
                  - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 1)
            )
            + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 1)
            AS int))
        Numbers.Number AS ID
        ,NULL AS ParentID
        ,1 AS Lvl
        ,CAST(
            (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
            (
                1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = 2)
                  - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 2)
            )
            + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 2)
            AS int) AS ChildRowCount
    FROM Numbers
    ORDER BY Numbers.Number

    UNION ALL

    SELECT
        CA.Number + CTE.ID * POWER(100, CTE.Lvl) AS ID
        ,CTE.ID AS ParentID
        ,CTE.Lvl + 1 AS Lvl
        ,CA.ChildRowCount
    FROM
        CTE
        CROSS APPLY
        (
            SELECT
                Numbers.Number
                ,CAST(
                    (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
                    (
                    1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                      - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                    )
                    + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                    AS int) AS ChildRowCount
            FROM Numbers
            WHERE Numbers.Number <= CTE.ChildRowCount
        ) AS CA
    WHERE
        CTE.ChildRowCount IS NOT NULL
)
SELECT *
FROM CTE
ORDER BY Lvl, ParentID, ID;

परिणाम (यदि आप भाग्यशाली हैं तो 20 + 20 * 10 + 200 * 5 = 1220 पंक्तियों तक हो सकते हैं)

+---------+----------+-----+-------------------+
|   ID    | ParentID | Lvl | ChildRowCount     |
+---------+----------+-----+-------------------+
|       1 | NULL     |   1 | 3                 |
|       2 | NULL     |   1 | 1                 |
|       3 | NULL     |   1 | 6                 |
|       4 | NULL     |   1 | 5                 |
|       5 | NULL     |   1 | 3                 |
|       6 | NULL     |   1 | 7                 |
|       7 | NULL     |   1 | 1                 |
|       8 | NULL     |   1 | 6                 |
|     101 | 1        |   2 | 3                 |
|     102 | 1        |   2 | 5                 |
|     103 | 1        |   2 | 1                 |
|     201 | 2        |   2 | 5                 |
|     301 | 3        |   2 | 4                 |
|     302 | 3        |   2 | 5                 |
|     303 | 3        |   2 | 1                 |
|     304 | 3        |   2 | 2                 |
|     305 | 3        |   2 | 4                 |
|     306 | 3        |   2 | 3                 |
|     401 | 4        |   2 | 3                 |
|     402 | 4        |   2 | 1                 |
|     403 | 4        |   2 | 2                 |
|     404 | 4        |   2 | 2                 |
|     405 | 4        |   2 | 4                 |
|     501 | 5        |   2 | 1                 |
|     502 | 5        |   2 | 3                 |
|     503 | 5        |   2 | 5                 |
|     601 | 6        |   2 | 2                 |
|     602 | 6        |   2 | 5                 |
|     603 | 6        |   2 | 3                 |
|     604 | 6        |   2 | 3                 |
|     605 | 6        |   2 | 4                 |
|     606 | 6        |   2 | 5                 |
|     607 | 6        |   2 | 4                 |
|     701 | 7        |   2 | 2                 |
|     801 | 8        |   2 | 2                 |
|     802 | 8        |   2 | 3                 |
|     803 | 8        |   2 | 3                 |
|     804 | 8        |   2 | 3                 |
|     805 | 8        |   2 | 5                 |
|     806 | 8        |   2 | 2                 |
| 1010001 | 101      |   3 | NULL              |
| 1010002 | 101      |   3 | NULL              |
| 1010003 | 101      |   3 | NULL              |
| 1020001 | 102      |   3 | NULL              |
| 1020002 | 102      |   3 | NULL              |
| 1020003 | 102      |   3 | NULL              |
| 1020004 | 102      |   3 | NULL              |
| 1020005 | 102      |   3 | NULL              |
| 1030001 | 103      |   3 | NULL              |
| 2010001 | 201      |   3 | NULL              |
| 2010002 | 201      |   3 | NULL              |
| 2010003 | 201      |   3 | NULL              |
| 2010004 | 201      |   3 | NULL              |
| 2010005 | 201      |   3 | NULL              |
| 3010001 | 301      |   3 | NULL              |
| 3010002 | 301      |   3 | NULL              |
| 3010003 | 301      |   3 | NULL              |
| 3010004 | 301      |   3 | NULL              |
| 3020001 | 302      |   3 | NULL              |
| 3020002 | 302      |   3 | NULL              |
| 3020003 | 302      |   3 | NULL              |
| 3020004 | 302      |   3 | NULL              |
| 3020005 | 302      |   3 | NULL              |
| 3030001 | 303      |   3 | NULL              |
| 3040001 | 304      |   3 | NULL              |
| 3040002 | 304      |   3 | NULL              |
| 3050001 | 305      |   3 | NULL              |
| 3050002 | 305      |   3 | NULL              |
| 3050003 | 305      |   3 | NULL              |
| 3050004 | 305      |   3 | NULL              |
| 3060001 | 306      |   3 | NULL              |
| 3060002 | 306      |   3 | NULL              |
| 3060003 | 306      |   3 | NULL              |
| 4010001 | 401      |   3 | NULL              |
| 4010002 | 401      |   3 | NULL              |
| 4010003 | 401      |   3 | NULL              |
| 4020001 | 402      |   3 | NULL              |
| 4030001 | 403      |   3 | NULL              |
| 4030002 | 403      |   3 | NULL              |
| 4040001 | 404      |   3 | NULL              |
| 4040002 | 404      |   3 | NULL              |
| 4050001 | 405      |   3 | NULL              |
| 4050002 | 405      |   3 | NULL              |
| 4050003 | 405      |   3 | NULL              |
| 4050004 | 405      |   3 | NULL              |
| 5010001 | 501      |   3 | NULL              |
| 5020001 | 502      |   3 | NULL              |
| 5020002 | 502      |   3 | NULL              |
| 5020003 | 502      |   3 | NULL              |
| 5030001 | 503      |   3 | NULL              |
| 5030002 | 503      |   3 | NULL              |
| 5030003 | 503      |   3 | NULL              |
| 5030004 | 503      |   3 | NULL              |
| 5030005 | 503      |   3 | NULL              |
| 6010001 | 601      |   3 | NULL              |
| 6010002 | 601      |   3 | NULL              |
| 6020001 | 602      |   3 | NULL              |
| 6020002 | 602      |   3 | NULL              |
| 6020003 | 602      |   3 | NULL              |
| 6020004 | 602      |   3 | NULL              |
| 6020005 | 602      |   3 | NULL              |
| 6030001 | 603      |   3 | NULL              |
| 6030002 | 603      |   3 | NULL              |
| 6030003 | 603      |   3 | NULL              |
| 6040001 | 604      |   3 | NULL              |
| 6040002 | 604      |   3 | NULL              |
| 6040003 | 604      |   3 | NULL              |
| 6050001 | 605      |   3 | NULL              |
| 6050002 | 605      |   3 | NULL              |
| 6050003 | 605      |   3 | NULL              |
| 6050004 | 605      |   3 | NULL              |
| 6060001 | 606      |   3 | NULL              |
| 6060002 | 606      |   3 | NULL              |
| 6060003 | 606      |   3 | NULL              |
| 6060004 | 606      |   3 | NULL              |
| 6060005 | 606      |   3 | NULL              |
| 6070001 | 607      |   3 | NULL              |
| 6070002 | 607      |   3 | NULL              |
| 6070003 | 607      |   3 | NULL              |
| 6070004 | 607      |   3 | NULL              |
| 7010001 | 701      |   3 | NULL              |
| 7010002 | 701      |   3 | NULL              |
| 8010001 | 801      |   3 | NULL              |
| 8010002 | 801      |   3 | NULL              |
| 8020001 | 802      |   3 | NULL              |
| 8020002 | 802      |   3 | NULL              |
| 8020003 | 802      |   3 | NULL              |
| 8030001 | 803      |   3 | NULL              |
| 8030002 | 803      |   3 | NULL              |
| 8030003 | 803      |   3 | NULL              |
| 8040001 | 804      |   3 | NULL              |
| 8040002 | 804      |   3 | NULL              |
| 8040003 | 804      |   3 | NULL              |
| 8050001 | 805      |   3 | NULL              |
| 8050002 | 805      |   3 | NULL              |
| 8050003 | 805      |   3 | NULL              |
| 8050004 | 805      |   3 | NULL              |
| 8050005 | 805      |   3 | NULL              |
| 8060001 | 806      |   3 | NULL              |
| 8060002 | 806      |   3 | NULL              |
+---------+----------+-----+-------------------+

लिंक किए गए पदानुक्रम के बजाय पूर्ण पथ बनाना

हम केवल पूर्ण पथ में रुचि रखते हैं Nगहरे स्तर, हम छोड़ सकते हैं IDऔर ParentIDCTE से। यदि हमारे पास पूरक तालिका में संभावित नामों की सूची है Names, तो सीटीई में उन्हें इस तालिका से चुनना आसान है। Names3 स्तर के लिए स्तर 2, 5 के लिए 1 स्तर, 10 के लिए 20;: तालिका प्रत्येक स्तर के लिए पर्याप्त पंक्तियों होना चाहिए कुल में 20 + 10 + 5 = 35। प्रत्येक स्तर के लिए पंक्तियों के अलग-अलग सेट होना आवश्यक नहीं है, लेकिन इसे ठीक से स्थापित करना आसान है, इसलिए मैंने ऐसा किया।

DECLARE @Names TABLE (Lvl int, Name nvarchar(4000), SeqNumber int);

-- First level: AAA, BBB, CCC, etc.
INSERT INTO @Names (Lvl, Name, SeqNumber)
SELECT 1, REPLICATE(CHAR(Number+64), 3) AS Name, Number AS SeqNumber
FROM Numbers
WHERE Number <= 20;

-- Second level: 001, 002, 003, etc.
INSERT INTO @Names (Lvl, Name, SeqNumber)
SELECT 2, REPLACE(STR(Number, 3), ' ', '0') AS Name, Number AS SeqNumber
FROM Numbers
WHERE Number <= 10;

-- Third level: I, II, III, IV, V
INSERT INTO @Names (Lvl, Name, SeqNumber) VALUES
(3, 'I',   1),
(3, 'II',  2),
(3, 'III', 3),
(3, 'IV',  4),
(3, 'V',   5);

एसक्यूएल फिडेल यहां अंतिम क्वेरी है। मैं विभाजित FullPathमें FilePathऔर FileName

WITH
CTE
AS
(
    SELECT 
        TOP(CAST(
            (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
            (
                1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = 1)
                  - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 1)
            )
            + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 1)
            AS int))

        1 AS Lvl
        ,CAST(
            (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
            (
                1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = 2)
                  - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 2)
            )
            + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = 2)
            AS int) AS ChildRowCount
        ,N.Name AS FullPath
        ,N.Name AS [FilePath]
        ,CAST(N'' AS nvarchar(4000)) AS [FileName]
    FROM
        Numbers
        INNER JOIN @Names AS N ON 
            N.SeqNumber = Numbers.Number AND N.Lvl = 1
    ORDER BY Numbers.Number

    UNION ALL

    SELECT
        CTE.Lvl + 1 AS Lvl
        ,CA.ChildRowCount
        ,CTE.FullPath + '\' + CA.Name AS FullPath

        ,CASE WHEN CA.ChildRowCount IS NOT NULL 
            THEN CTE.FullPath + '\' + CA.Name
            ELSE CTE.FullPath END AS [FilePath]

        ,CASE WHEN CA.ChildRowCount IS NULL 
            THEN CA.Name
            ELSE N'' END AS [FileName]
    FROM
        CTE
        CROSS APPLY
        (
            SELECT
                Numbers.Number
                ,CAST(
                    (CAST(CRYPT_GEN_RANDOM(4) as int) / 4294967295.0 + 0.5) * 
                    (
                    1 + (SELECT I.LvlMax FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                      - (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                    )
                    + (SELECT I.LvlMin FROM @Intervals AS I WHERE I.Lvl = CTE.Lvl + 2)
                    AS int) AS ChildRowCount
                ,N.Name
            FROM
                Numbers
                INNER JOIN @Names AS N ON 
                    N.SeqNumber = Numbers.Number AND N.Lvl = CTE.Lvl + 1
            WHERE Numbers.Number <= CTE.ChildRowCount
        ) AS CA
    WHERE
        CTE.ChildRowCount IS NOT NULL
)
SELECT
    CTE.FullPath
    ,CTE.[FilePath]
    ,CTE.[FileName]
FROM CTE
WHERE CTE.ChildRowCount IS NULL
ORDER BY FullPath;

परिणाम

+-------------+----------+----------+
|  FullPath   | FilePath | FileName |
+-------------+----------+----------+
| AAA\001\I   | AAA\001  | I        |
| AAA\001\II  | AAA\001  | II       |
| AAA\002\I   | AAA\002  | I        |
| AAA\002\II  | AAA\002  | II       |
| AAA\002\III | AAA\002  | III      |
| AAA\002\IV  | AAA\002  | IV       |
| AAA\002\V   | AAA\002  | V        |
| AAA\003\I   | AAA\003  | I        |
| AAA\003\II  | AAA\003  | II       |
| AAA\003\III | AAA\003  | III      |
| AAA\004\I   | AAA\004  | I        |
| AAA\004\II  | AAA\004  | II       |
| AAA\004\III | AAA\004  | III      |
| AAA\004\IV  | AAA\004  | IV       |
| BBB\001\I   | BBB\001  | I        |
| BBB\001\II  | BBB\001  | II       |
| CCC\001\I   | CCC\001  | I        |
| CCC\001\II  | CCC\001  | II       |
| CCC\001\III | CCC\001  | III      |
| CCC\001\IV  | CCC\001  | IV       |
| CCC\001\V   | CCC\001  | V        |
| CCC\002\I   | CCC\002  | I        |
| CCC\003\I   | CCC\003  | I        |
| CCC\003\II  | CCC\003  | II       |
| CCC\004\I   | CCC\004  | I        |
| CCC\004\II  | CCC\004  | II       |
| CCC\005\I   | CCC\005  | I        |
| CCC\005\II  | CCC\005  | II       |
| CCC\005\III | CCC\005  | III      |
| CCC\006\I   | CCC\006  | I        |
| CCC\006\II  | CCC\006  | II       |
| CCC\006\III | CCC\006  | III      |
| CCC\006\IV  | CCC\006  | IV       |
| CCC\007\I   | CCC\007  | I        |
| CCC\007\II  | CCC\007  | II       |
| CCC\007\III | CCC\007  | III      |
| CCC\007\IV  | CCC\007  | IV       |
| CCC\008\I   | CCC\008  | I        |
| CCC\008\II  | CCC\008  | II       |
| CCC\008\III | CCC\008  | III      |
| CCC\009\I   | CCC\009  | I        |
| CCC\009\II  | CCC\009  | II       |
| CCC\009\III | CCC\009  | III      |
| CCC\009\IV  | CCC\009  | IV       |
| CCC\010\I   | CCC\010  | I        |
| CCC\010\II  | CCC\010  | II       |
| CCC\010\III | CCC\010  | III      |
| DDD\001\I   | DDD\001  | I        |
| DDD\001\II  | DDD\001  | II       |
| DDD\001\III | DDD\001  | III      |
| DDD\001\IV  | DDD\001  | IV       |
| DDD\002\I   | DDD\002  | I        |
| DDD\003\I   | DDD\003  | I        |
| DDD\003\II  | DDD\003  | II       |
| DDD\003\III | DDD\003  | III      |
| DDD\003\IV  | DDD\003  | IV       |
| DDD\004\I   | DDD\004  | I        |
| DDD\004\II  | DDD\004  | II       |
| DDD\004\III | DDD\004  | III      |
| DDD\005\I   | DDD\005  | I        |
| DDD\006\I   | DDD\006  | I        |
| DDD\006\II  | DDD\006  | II       |
| DDD\006\III | DDD\006  | III      |
| DDD\007\I   | DDD\007  | I        |
| DDD\007\II  | DDD\007  | II       |
| DDD\008\I   | DDD\008  | I        |
| DDD\008\II  | DDD\008  | II       |
| DDD\008\III | DDD\008  | III      |
| DDD\009\I   | DDD\009  | I        |
| DDD\009\II  | DDD\009  | II       |
| DDD\010\I   | DDD\010  | I        |
| DDD\010\II  | DDD\010  | II       |
| DDD\010\III | DDD\010  | III      |
| DDD\010\IV  | DDD\010  | IV       |
| DDD\010\V   | DDD\010  | V        |
| EEE\001\I   | EEE\001  | I        |
| EEE\001\II  | EEE\001  | II       |
| FFF\001\I   | FFF\001  | I        |
| FFF\002\I   | FFF\002  | I        |
| FFF\002\II  | FFF\002  | II       |
| FFF\003\I   | FFF\003  | I        |
| FFF\003\II  | FFF\003  | II       |
| FFF\003\III | FFF\003  | III      |
| FFF\003\IV  | FFF\003  | IV       |
| FFF\003\V   | FFF\003  | V        |
| FFF\004\I   | FFF\004  | I        |
| FFF\004\II  | FFF\004  | II       |
| FFF\004\III | FFF\004  | III      |
| FFF\004\IV  | FFF\004  | IV       |
| FFF\005\I   | FFF\005  | I        |
| FFF\006\I   | FFF\006  | I        |
| FFF\007\I   | FFF\007  | I        |
| FFF\007\II  | FFF\007  | II       |
| FFF\007\III | FFF\007  | III      |
| GGG\001\I   | GGG\001  | I        |
| GGG\001\II  | GGG\001  | II       |
| GGG\001\III | GGG\001  | III      |
| GGG\002\I   | GGG\002  | I        |
| GGG\003\I   | GGG\003  | I        |
| GGG\003\II  | GGG\003  | II       |
| GGG\003\III | GGG\003  | III      |
| GGG\004\I   | GGG\004  | I        |
| GGG\004\II  | GGG\004  | II       |
| HHH\001\I   | HHH\001  | I        |
| HHH\001\II  | HHH\001  | II       |
| HHH\001\III | HHH\001  | III      |
| HHH\002\I   | HHH\002  | I        |
| HHH\002\II  | HHH\002  | II       |
| HHH\002\III | HHH\002  | III      |
| HHH\002\IV  | HHH\002  | IV       |
| HHH\002\V   | HHH\002  | V        |
| HHH\003\I   | HHH\003  | I        |
| HHH\003\II  | HHH\003  | II       |
| HHH\003\III | HHH\003  | III      |
| HHH\003\IV  | HHH\003  | IV       |
| HHH\003\V   | HHH\003  | V        |
| HHH\004\I   | HHH\004  | I        |
| HHH\004\II  | HHH\004  | II       |
| HHH\004\III | HHH\004  | III      |
| HHH\004\IV  | HHH\004  | IV       |
| HHH\004\V   | HHH\004  | V        |
| HHH\005\I   | HHH\005  | I        |
| HHH\005\II  | HHH\005  | II       |
| HHH\005\III | HHH\005  | III      |
| HHH\005\IV  | HHH\005  | IV       |
| HHH\005\V   | HHH\005  | V        |
| HHH\006\I   | HHH\006  | I        |
| HHH\007\I   | HHH\007  | I        |
| HHH\007\II  | HHH\007  | II       |
| HHH\007\III | HHH\007  | III      |
| HHH\008\I   | HHH\008  | I        |
| HHH\008\II  | HHH\008  | II       |
| HHH\008\III | HHH\008  | III      |
| HHH\008\IV  | HHH\008  | IV       |
| HHH\008\V   | HHH\008  | V        |
+-------------+----------+----------+

दिलचस्प दृष्टिकोण :)। मुझें यह पसंद है। पूर्णता की खातिर, क्या आप संख्या तालिका (SQL फिडेल से) को पॉप्युलेट करने के लिए क्वेरी जोड़ सकते हैं, या CTE के हिस्से के रूप में उस इनलाइन को शामिल कर सकते हैं? तब किसी के लिए सिर्फ कॉपी और पेस्ट करना आसान होता है। इस उत्तर के लिए, क्या अंतिम उत्पादन को प्रत्येक पंक्ति के रूप में व्यक्त किया जा सकता है, जो Level1 से Level3 तक सभी Level3 मानों के लिए एक पूर्ण पथ है? मुझे लगता है कि INNER JOINफाइनल में सिर्फ 2 एस लगेगा SELECT। अंत में, नाम / लेबल प्रत्येक नोड को सौंपा जा सकता है ताकि वे सिर्फ संख्याएं न हों? मैं इन दोनों बिंदुओं को स्पष्ट करने के लिए प्रश्न को अपडेट करूंगा।
सोलोमन रटज़की

ये नाम / लेबल कहां से आते हैं? क्या मेरे पास एक 'नाम' तालिका होनी चाहिए, जिसमें 20 पंक्तियाँ हों और उसमें से कोई नाम चुनें? इस प्रकार प्रत्येक स्तर पर नामों का एक ही सेट दिखाई देगा। या प्रत्येक स्तर के नाम का अपना अलग सेट होना चाहिए?
व्लादिमीर बारानोव

मुझे लगता है कि नाम CTE के हिस्से के रूप में या तो एक टेबल (अस्थायी, वास्तविक, या चर) या इनलाइन से आ सकते हैं। मैंने मूल रूप से उन्हें सीटीई में रखा था, लेकिन फिर उन्हें एक स्थानीय अस्थायी तालिका में स्थानांतरित कर दिया ताकि क्वेरी का मुख्य भाग यहां अधिक पठनीय हो। मुझे लगता है कि आपके पास जो संरचना है, वह प्रति स्तर अलग होना आसान होगा। लेकिन अगर यह सिर्फ 20 का एक सेट था जो कि पर्याप्त होगा, तो यह सिर्फ परीक्षण डेटा में थोड़ा कम बदलाव प्रदान करता है। केवल वास्तविक आवश्यकता यह है कि कोई भी नाम नोड के भीतर दोहराता नहीं है क्योंकि निर्देशिका या फ़ाइलों को बनाने की कोशिश करते समय त्रुटि होगी :)।
सोलोमन रटज़की

1
@ श्रुतस्की, मैंने एक दूसरा संस्करण जोड़ा।
व्लादिमीर बारानोव

1
@ श्रुतस्की, मैं और FullPathमें विभाजित हो गया । FilePathFileName
व्लादिमीर बारानोव

4

तो यहाँ है क्या मैं के साथ आया था। निर्देशिका संरचना बनाने के लक्ष्य के साथ, मैं निर्देशिकाओं और फ़ाइलों के लिए प्रयोग करने योग्य "नामों" की तलाश कर रहा था। चूँकि मैं एस TOP(n)में काम करने में असमर्थ था CROSS APPLY(मुझे लगता है कि मैंने माता-पिता से मूल्य का उपयोग करके प्रश्नों को सहसंबंधित करने का प्रयास किया nथा, TOP(n)लेकिन तब यह यादृच्छिक नहीं था), मैंने एक प्रकार की "संख्या" बनाने का फैसला किया तालिका जो किसी संख्या को यादृच्छिक रूप से और इसे निर्दिष्ट करके तत्वों के एक सेट का उत्पादन करने के लिए INNER JOINया WHEREस्थिति की अनुमति देती है । चाल यह है कि Level1 के लिए केवल 1 पंक्ति है, Level2 के लिए 2 पंक्तियाँ, Level3 के लिए 3 पंक्तियाँ, और इसी तरह। इसलिए, उपयोग करने से मुझे 3 पंक्तियां मिलेंगी, और प्रत्येक पंक्ति का एक मूल्य है जिसे मैं निर्देशिका नाम के रूप में उपयोग कर सकता हूं।nWHERE table.Level = random_numberWHERE LevelID = 3

सेट अप

यह भाग मूल रूप से CTE के हिस्से के रूप में इनलाइन निर्दिष्ट किया गया था। लेकिन पठनीयता के लिए (ताकि आपको INSERTवास्तविक क्वेरी की कुछ पंक्तियों तक पहुंचने के लिए बहुत सारे बयानों को स्क्रॉल करने की आवश्यकता न हो), मैंने इसे एक स्थानीय अस्थायी तालिका में तोड़ दिया।

IF (OBJECT_ID(N'tempdb..#Elements') IS NULL)
BEGIN
  PRINT 'Creating #Elements table...';
  CREATE TABLE #Elements (
     ElementLevel TINYINT NOT NULL,
     LevelName NVARCHAR(50) NOT NULL
                         );

  PRINT 'Populating #Elements table...';
  INSERT INTO #Elements (ElementLevel, LevelName)
    SELECT tmp.[Level], tmp.[Name]
    FROM (
                  SELECT 1,  N'Ella'
       UNION ALL  SELECT 2,  N'Itchy'
       UNION ALL  SELECT 2,  N'Scratchy'
       UNION ALL  SELECT 3,  N'Moe'
       UNION ALL  SELECT 3,  N'Larry'
       UNION ALL  SELECT 3,  N'Curly'
       UNION ALL  SELECT 4,  N'Ian'
       UNION ALL  SELECT 4,  N'Stephen'
       UNION ALL  SELECT 4,  N'Peter'
       UNION ALL  SELECT 4,  N'Bernard'
       UNION ALL  SELECT 5,  N'Michigan'
       UNION ALL  SELECT 5,  N'Erie'
       UNION ALL  SELECT 5,  N'Huron'
       UNION ALL  SELECT 5,  N'Ontario'
       UNION ALL  SELECT 5,  N'Superior'
       UNION ALL  SELECT 6,  N'White'
       UNION ALL  SELECT 6,  N'Orange'
       UNION ALL  SELECT 6,  N'Blonde'
       UNION ALL  SELECT 6,  N'Pink'
       UNION ALL  SELECT 6,  N'Blue'
       UNION ALL  SELECT 6,  N'Brown'
       UNION ALL  SELECT 7,  N'Asia'
       UNION ALL  SELECT 7,  N'Africa'
       UNION ALL  SELECT 7,  N'North America'
       UNION ALL  SELECT 7,  N'South America'
       UNION ALL  SELECT 7,  N'Antarctica'
       UNION ALL  SELECT 7,  N'Europe'
       UNION ALL  SELECT 7,  N'Australia'
       UNION ALL  SELECT 8,  N'AA'
       UNION ALL  SELECT 8,  N'BB'
       UNION ALL  SELECT 8,  N'CC'
       UNION ALL  SELECT 8,  N'DD'
       UNION ALL  SELECT 8,  N'EE'
       UNION ALL  SELECT 8,  N'FF'
       UNION ALL  SELECT 8,  N'GG'
       UNION ALL  SELECT 8,  N'HH'
       UNION ALL  SELECT 9,  N'I'
       UNION ALL  SELECT 9,  N'II'
       UNION ALL  SELECT 9,  N'III'
       UNION ALL  SELECT 9,  N'IV'
       UNION ALL  SELECT 9,  N'V'
       UNION ALL  SELECT 9,  N'VI'
       UNION ALL  SELECT 9,  N'VII'
       UNION ALL  SELECT 9,  N'VIII'
       UNION ALL  SELECT 9,  N'IX'
       UNION ALL  SELECT 10, N'Million'
       UNION ALL  SELECT 10, N'Billion'
       UNION ALL  SELECT 10, N'Trillion'
       UNION ALL  SELECT 10, N'Quadrillion'
       UNION ALL  SELECT 10, N'Quintillion'
       UNION ALL  SELECT 10, N'Sestillion'
       UNION ALL  SELECT 10, N'Sextillion'
       UNION ALL  SELECT 10, N'Octillion'
       UNION ALL  SELECT 10, N'Nonillion'
       UNION ALL  SELECT 10, N'Decillion'
     ) tmp([Level], [Name]);
END;

मुख्य प्रश्न

लेवल 1 के लिए मैंने अभी से [name]मानों को पकड़ लिया है sys.objectsक्योंकि वहाँ हमेशा बहुत सारी पंक्तियाँ होती हैं। लेकिन, अगर मुझे नामों पर अधिक नियंत्रण की आवश्यकता है, तो मैं #Elementsअतिरिक्त स्तरों को शामिल करने के लिए तालिका का विस्तार कर सकता हूं ।

;WITH topdir(Level1, Randy) AS
(
    SELECT TOP ( (CONVERT(INT, CRYPT_GEN_RANDOM(1)) % 20) + 5 ) so.[name],
                ( (CONVERT(INT, CRYPT_GEN_RANDOM(1)) % 10) + 1 )
    FROM sys.objects so
    ORDER BY CRYPT_GEN_RANDOM(8) ASC
)
SELECT  td.Level1, tmp1.Level2, tmp2.Level3
FROM    topdir td
CROSS APPLY (SELECT help.LevelName, (CONVERT(INT, CRYPT_GEN_RANDOM(1)) % 5) + 1
            FROM #Elements help
            WHERE help.ElementLevel = td.Randy
            ) tmp1 (Level2, Bandy)
CROSS APPLY (SELECT help.LevelName
            FROM #Elements help
            WHERE help.ElementLevel = tmp1.Bandy
            ) tmp2 (Level3);

प्रत्येक व्यक्ति के पेट, नाम और सामग्री का उत्पादन करने के लिए कहा जाता है

फ़ाइलों और फ़ाइल सामग्री के लिए पूर्ण पथ उत्पन्न करने के लिए, मैंने सीटीई के मुख्य चयन को केवल एक और सीटीई बनाया और एक नया मुख्य चयन जोड़ा जिसने उचित आउटपुट दिए जो कि केवल फाइलों में जाने की आवश्यकता है।

DECLARE @Template NVARCHAR(4000);
SET @Template = N'<?xml version="1.0" encoding="ISO-8859-1"?>
<ns0:P4131 xmlns:ns0="http://switching/xi">
<R000000>
    <R00000010>R000000</R00000010>
    <R00000020>I</R00000020>
    <R00000030>{{Tag30}}</R00000030>
    <R00000040>{{Tag40}}</R00000040>
    <R00000050>{{Tag50}}</R00000050>
    <R00000060>2</R00000060>
</R000000>
</ns0:P4131>
';


;WITH topdir(Level1, Thing1) AS
(
    SELECT TOP ( (CONVERT(INT, CRYPT_GEN_RANDOM(1)) % 20) + 5 ) so.[name],
                ( (CONVERT(INT, CRYPT_GEN_RANDOM(1)) % 10) + 1 )
    FROM sys.objects so
    ORDER BY CRYPT_GEN_RANDOM(8) ASC
), main AS
(
   SELECT  td.Level1, tmp1.Level2, tmp2.Level3,
           td.Level1 + N'\' + tmp1.Level2 AS [FullPath],
           RIGHT('000' + CONVERT(VARCHAR(10),
                          (CONVERT(INT, CRYPT_GEN_RANDOM(2)) % 9999) + 1), 4) AS [R30],
           RIGHT('000' + CONVERT(VARCHAR(10),
                          (CONVERT(INT, CRYPT_GEN_RANDOM(2)) % 500) + 100), 4) AS [R50],
           ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS [RowNum]
   FROM    topdir td
   CROSS APPLY (SELECT help.LevelName, (CONVERT(INT, CRYPT_GEN_RANDOM(1)) % 5) + 1
                FROM #Elements help
                WHERE help.ElementLevel = td.Thing1
               ) tmp1 (Level2, Thing2)
   CROSS APPLY (SELECT help.LevelName
                FROM #Elements help
                WHERE help.ElementLevel = tmp1.Thing2
               ) tmp2 (Level3)
)
SELECT  mn.FullPath,
        mn.Level3 + N'.xml' AS [FileName],
        REPLACE(
            REPLACE(
                REPLACE(
                    @Template,
                    N'{{Tag30}}',
                    mn.R30),
                N'{{Tag40}}',
                mn.RowNum),
            N'{{Tag50}}',
            mn.R50) AS [Contents]
FROM    main mn;

अतिरिक्त श्रेय

प्रश्न में बताई गई आवश्यकताओं का हिस्सा नहीं होने पर, लक्ष्य (जिसका उल्लेख किया गया था) के साथ पुनरावर्ती फ़ाइल सिस्टम फ़ंक्शन का परीक्षण करने के लिए फ़ाइलें बनाना था। तो हम इस परिणाम को पथ नाम, फ़ाइल नाम और फ़ाइल सामग्री के सेट के साथ कैसे लेते हैं और इसके साथ कुछ करते हैं? हमें केवल दो SQLCLR फ़ंक्शन की आवश्यकता है: एक फ़ोल्डर बनाने के लिए और एक फाइल बनाने के लिए।

इस डेटा को कार्यात्मक बनाने के लिए, मैंने SELECTऊपर दिखाए गए CTE के मुख्य को सीधे नीचे संशोधित किया है:

SELECT  SQL#.File_CreateDirectory(
            N'C:\Stuff\TestXmlFiles\' + mn.FullPath) AS [CreateTheDirectory],
        SQL#.File_WriteFile(
            N'C:\Stuff\TestXmlFiles\' + mn.FullPath + N'\' + mn.Level3 + N'.xml',
            REPLACE(
                REPLACE(
                    REPLACE(
                        @Template,
                        N'{{Tag30}}',
                        mn.R30),
                    N'{{Tag40}}',
                    mn.RowNum),
                N'{{Tag50}}',
                mn.R50), -- @FileData
            0, -- @AppendData
            '' -- @FileEncoding
                            ) AS [WriteTheFile]
FROM    main mn;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.