2011-06-20 19 views
5

मेरे पास है (पार्स अल्पविराम व्यक्तिगत रिकॉर्ड में खेतों विभाजित) इस तरह एक मेज:टेबल सामान्यीकरण

डिवाइस

DeviceId Parts 

1   Part1, Part2, Part3 
2   Part2, Part3, Part4 
3   Part1 

मैं पार्ट्स से एक मेज 'पार्ट्स', निर्यात डेटा बनाना चाहेंगे नई तालिका में कॉलम। मुझे लगता है कि

अपेक्षित परिणाम के बाद पार्ट्स स्तंभ छोड़ देंगे

पार्ट्स

PartId PartName 

    1  Part1 
    2  Part2 
    3  Part3 
    4  Part4 

DevicePart

DeviceId PartId 

    1  1 
    1  2 
    1  3 
    2  2 
    2  3 
    2  4 
    3  1 

मैं एसक्यूएल सर्वर 2008 में यह कर सकता कर्सर का उपयोग किए बिना?

+0

क्या आप अब तक की कोशिश की है। आपको यहां एक संकेत है जो partID (Int, Identity (1,1)), partname के साथ एक तालिका है और उसमें एक अलग चयन के साथ डालें .. उसके बाद एक जुड़ने के बाद आपको दूसरी तालिका मिल जाएगी .. – Ash

+0

मैंने अब तक कर्सर की कोशिश की है लेकिन मुझे समाधान पसंद नहीं है और मुझे लगता है कि ऐसा करने का एक बेहतर तरीका होना चाहिए। –

उत्तर

5

- सेटअप:

declare @Device table(DeviceId int primary key, Parts varchar(1000)) 
declare @Part table(PartId int identity(1,1) primary key, PartName varchar(100)) 
declare @DevicePart table(DeviceId int, PartId int) 

insert @Device 
values 
    (1, 'Part1, Part2, Part3'), 
    (2, 'Part2, Part3, Part4'), 
    (3, 'Part1') 

--Script:

declare @DevicePartTemp table(DeviceId int, PartName varchar(100)) 

insert @DevicePartTemp 
select DeviceId, ltrim(x.value('.', 'varchar(100)')) 
from 
(
    select DeviceId, cast('<x>' + replace(Parts, ',', '</x><x>') + '</x>' as xml) XmlColumn 
    from @Device 
)tt 
cross apply 
    XmlColumn.nodes('x') as Nodes(x) 


insert @Part 
select distinct PartName 
from @DevicePartTemp 

insert @DevicePart 
select tmp.DeviceId, prt.PartId 
from @DevicePartTemp tmp 
    join @Part prt on 
     prt.PartName = tmp.PartName 

- परिणाम:

select * 
from @Part 

PartId  PartName 
----------- --------- 
1   Part1 
2   Part2 
3   Part3 
4   Part4 


select * 
from @DevicePart 

DeviceId PartId 
----------- ----------- 
1   1 
1   2 
1   3 
2   2 
2   3 
2   4 
3   1 
0

अल्पविराम से अलग मूल्यों से तालिका चर बनाने के लिए fn_Split का उपयोग करने पर एक नज़र डालें। फिर आप अपने सम्मिलित करने के लिए इसका उपयोग कर सकते हैं।

संपादित करें: असल में, मुझे लगता है कि आपको अभी भी कर्सर की आवश्यकता हो सकती है। इस उत्तर को छोड़कर fn_Split मदद करता है।

+0

लॉर्डी, कृपया उस फ़ंक्शन का उपयोग न करें। यह एक एमटीवीएफ और एक WHILE पाश का उपयोग करता है। यह उपलब्ध सबसे धीमे स्प्लिटर में से एक है। –

0

यदि डिवाइस प्रति डिवाइस की अधिकतम संख्या है तो हाँ, यह कर्सर के बिना किया जा सकता है, लेकिन यह काफी जटिल है।

अनिवार्य रूप से, एक तालिका (या देखें या सबक्वायरी) बनाएं जिसमें पार्टिड स्ट्रिंग में प्रत्येक संभावित अनुक्रमणिका के लिए डिवाइस आईडी और एक पार्टिड कॉलम हो। यह partID कॉलम को fn_split या अपनी पसंद की दूसरी विधि का उपयोग करके कॉलम की गणना करके पूरा किया जा सकता है। वहां से आप प्रत्येक तालिका कॉलम के लिए स्वयं-यूनियन में एक तालिका के साथ, इस तालिका का एक से अधिक स्वयं-यूनियन करते हैं। स्वयं-यूनियन में प्रत्येक तालिका में तालिका के लिए क्वेरी की चयन सूची में शामिल पार्टिड कॉलम में से केवल एक है।

1

आपको कर्सर के बिना इसे पूरा करने के लिए टैली तालिका की आवश्यकता होगी। , Tally Tables by Jeff Moden

यह स्क्रिप्ट अपने अस्थायी डेटाबेस में तालिका डाल देंगे तो आप शायद "उपयोग डीबी" बयान बदलने के लिए

तो फिर तुम चला सकते हैं हैं:

यहाँ एक मिलान तालिका बनाने के लिए निर्देशों का पालन करें उपकरणों और हिस्सों को एक अस्थायी तालिका में तोड़ने के लिए नीचे दी गई स्क्रिप्ट। इसके बाद आपको भाग भाग (आईडी प्राप्त करने के लिए) द्वारा अपनी पार्ट तालिका में शामिल होने और अपनी नई डिवाइसपार्ट तालिका में डालने में सक्षम होना चाहिए।

select *, 
--substring(d.parts, 1, t.n) 
substring(d.parts, t.n, charindex(', ', d.parts + ', ',t.n) - t.n) 'Part' 
into #devicesparts 
from device d 
cross join tally t 
where t.n < (select max(len(parts))+ 1 from device) 
and substring(', ' + d.parts, t.n, 1) = ', ' 
संबंधित मुद्दे