2016-05-25 10 views
5

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

CREATE TABLE [dbo].[TempWords] 
(
    [Id]   INT   IDENTITY (1, 1) NOT NULL, 
    [Word]  NVARCHAR (MAX) NOT NULL, 
    [WordForms] NVARCHAR (MAX) NULL, 
) 

मैं दो तालिकाओं को भरने के लिए इस डेटा का उपयोग करना चाहते हैं: और कुछ अभी पिछले wordform शब्द

Id Word  WordForms 
1 abandon abandoned, abandoning, abandonment, abandons  
2 abstract abstraction, abstractions, abstractly, abstracts, e.g. 

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

CREATE TABLE [dbo].[Words] 
(
    [WordId]  INT   IDENTITY (1, 1) NOT NULL, 
    [Word]  NVARCHAR (MAX) NOT NULL 
) 

CREATE TABLE [dbo].[WordForms] 
(
    [Id]   INT   IDENTITY (1, 1) NOT NULL, 
    [WordId]  INT NOT NULL, 
    [Text] NVARCHAR (MAX) NULL, 
) 

क्या कोई मुझे कुछ सुझाव दे सकता है कि मैं यह कैसे कर सकता हूं?

+0

आप कैसे आप tempwords डेटा को अलग करना चाहते हैं उसका उदाहरण दिखा सकता है (डेटा के साथ दिखाया गया प्रश्न में) अन्य टेबल – TheGameiswar

उत्तर

7

सबसे पहले, आप सीएसवी मानों को अलग करने के लिए यूडीएफ फ़ंक्शन बना सकते हैं।

CREATE FUNCTION dbo.fn_Split (
     @InputString     VARCHAR(8000), 
     @Delimiter     VARCHAR(50) 
) 

RETURNS @Items TABLE (
     Item       VARCHAR(8000) 
) 

AS 
BEGIN 
     IF @Delimiter = ' ' 
     BEGIN 
      SET @Delimiter = ',' 
      SET @InputString = REPLACE(@InputString, ' ', @Delimiter) 
     END 

     IF (@Delimiter IS NULL OR @Delimiter = '') 
      SET @Delimiter = ',' 

--INSERT INTO @Items VALUES (@Delimiter) -- Diagnostic 
--INSERT INTO @Items VALUES (@InputString) -- Diagnostic 

     DECLARE @Item     VARCHAR(8000) 
     DECLARE @ItemList  VARCHAR(8000) 
     DECLARE @DelimIndex  INT 

     SET @ItemList = @InputString 
     SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0) 
     WHILE (@DelimIndex != 0) 
     BEGIN 
      SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex) 
      INSERT INTO @Items VALUES (@Item) 

      -- Set @ItemList = @ItemList minus one less item 
      SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)[email protected]) 
      SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0) 
     END -- End WHILE 

     IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString 
     BEGIN 
      SET @Item = @ItemList 
      INSERT INTO @Items VALUES (@Item) 
     END 

     -- No delimiters were encountered in @InputString, so just return @InputString 
     ELSE INSERT INTO @Items VALUES (@InputString) 

     RETURN 

END -- End Function 
GO 

तो फिर तुम टेबल पॉप्युलेट करने के लिए सम्मिलित करें बयान नीचे का उपयोग कर सकते हैं।

INSERT INTO [Words] 
SELECT Word FROM TempWords 


INSERT INTO WordForms 

SELECT 
    W.WordId, 
    LTRIM(RTRIM(FNT.Item)) AS Item 
FROM TempWords AS TW 
INNER JOIN [Words] AS W 
ON TW.[Word]=W.[Word] 
CROSS APPLY fn_Split(REPLACE(TW.WordForms,', e.g.',''),',') AS FNT 


SELECT * FROM [Words] 
SELECT * FROM WordForms 
+0

आपके बहुत विस्तृत उत्तर के लिए बहुत बहुत धन्यवाद wer। मैं इसका परीक्षण करूंगा और आपको अपडेट करूँगा। एक चीज शायद गायब हो सकती है। मूल डेटा में वर्डफ़ॉर्म कॉलम में कभी-कभी ", उदाहरण" होता है शब्दों की सूची के अंत में और कभी-कभी यह नहीं करता है। क्या कोई तरीका है इसे फ़िल्टर किया जा सकता है? यदि नहीं तो मुझे लगता है कि यह WordForms तालिका को टेक्स्ट के साथ कई पंक्तियों के साथ पॉप्युलेट करने जा रहा है ", उदाहरण के लिए" - धन्यवाद –

+1

मैंने 'वर्डफ़ॉर्म' कॉलम से REPLACE फ़ंक्शन को शामिल करने के लिए कोड अपडेट किया है। यह ", उदाहरण के लिए" की सभी घटनाओं को हटा देगा 'वर्डफॉर्म' कॉलम से। – Sandesh

+0

@SandeshP - मुझे वास्तविक तालिकाओं से पहले कुछ परीक्षण डेटा पर आपके समाधान का परीक्षण करने की आवश्यकता होगी। मैं आपका जवाब अपडेट करूंगा और आपको बताऊंगा कि चीजें कैसे चलती हैं लेकिन मेरे लिए सब कुछ जांचने में कुछ समय लगेगा। आपके सहयोग के लिए धन्यवाद। जल्द ही सवाल स्वीकार करने में सक्षम होने की उम्मीद है। अगर मेरे पास बाद में कोई और टिप्पणी है तो कृपया वापस जांचें। –

5

आप पहली बार तालिका में शब्द सम्मिलित कर सकते हैं, पार्स शब्द रूपों की तुलना में और उन्हें माता-पिता की मेज के लिए लिंक के साथ बच्चे तालिका में सम्मिलित करें। माता-पिता मेज पर

लिंक (मुझे लगता है कि यह अद्वितीय है) word स्तंभ पर शामिल होने से या एक कदम SOURCE.ID में प्राप्त करने के लिए कुछ MERGE + OUTPUT बात कर के द्वारा प्राप्त किया जा सकता है (से @words_csv) और INSERTED.ID। किसी भी तरह से आप पसंद करते हैं।

पार्सिंग कई मायनों में भी लागू किया जा सकता, इस उदाहरण की जाँच (वास्तव में मैं एसक्यूएल बिल्कुल साथ पार्स के लिए सिफारिश नहीं होगा)।

DECLARE @words_csv TABLE (Id INT IDENTITY(1, 1), Word VARCHAR(100), WordForms VARCHAR(1000)) 

INSERT INTO @words_csv(word, wordforms) 
VALUES 
    ('abandon', 'abandoned, abandoning, abandonment, abandons, e.g.'), 
    ('abstract', 'abstraction, abstractions, abstractly, abstracts') 

--INSERT INTO [dbo].[Words](word) 
--SELECT w.word 
--FROM @words_csv w 

;WITH word_forms_extracted AS 
    (
     SELECT w.id, 
       w.word, 
       ltrim(rtrim(cast(case when CHARINDEX(',', w.WordForms) > 0 then substring(w.wordforms, 1, CHARINDEX(',', w.WordForms)-1) end AS VARCHAR(1000)))) wordform, 
       stuff(w.wordforms, 1, CHARINDEX(',', w.WordForms), '') wordforms 
     FROM @words_csv w 

     UNION ALL 

     SELECT w.id, 
       w.word, 
       ltrim(rtrim(cast(case when CHARINDEX(',', wfe.WordForms) > 0 then substring(wfe.wordforms, 1, CHARINDEX(',', wfe.WordForms)-1) else wfe.wordforms end AS VARCHAR(1000)))) wordform, 
       case when CHARINDEX(',', wfe.WordForms) > 0 then stuff(wfe.wordforms, 1, CHARINDEX(',', wfe.WordForms), '') ELSE '' end wordforms 
     FROM @words_csv w 
       INNER JOIN word_forms_extracted wfe 
        ON wfe.id = w.id 
     WHERE wfe.wordforms != '' 
    ) 
SELECT wf.id, wf.word, wf.wordform 
FROM word_forms_extracted wf 
--INNER JOIN [dbo].[Words] w 
--ON w.word = wf.word 
WHERE wf.wordform NOT IN ('', 'e.g.') 
ORDER BY wf.id, wf.wordform 
OPTION(MAXRECURSION 1000) 

अंतिम SELECT आसानी से dbo.Words करने के लिए INSERT INTO dbo.WordForms (...) SELECT ... लिंक संशोधित किया जा सकता के रूप में आप word स्तंभ पर शामिल होने से देख सकते हैं यहाँ प्राप्त की है।

+0

हाय इवान, स्रोत स्रोत पंक्तियों में से कुछ ", उदाहरण के लिए" उनके अंत में और कुछ नहीं करते हैं। क्या आप ", उदा।" को अस्वीकार करने के लिए संशोधित कोड को संशोधित कर सकते हैं वर्डफ़ॉर्म कॉलम में स्रोत डेटा के अंत में यह कहां दिखाई देता है? –

+0

चूंकि हमें पार्स किए गए वर्डफॉर्म मिलते हैं, 'उदा।' सरल 'कहां' predicate द्वारा फ़िल्टर किया जा सकता है। या जिस तरह से @ सांडेश ने किया - पार्सिंग से पहले हटा दिया। और इस उदाहरण को चलाने और परीक्षण करने में आसान बनाने के लिए अपनी स्थिर सारणी पर टिप्पणी की। –

+0

वास्तव में यह स्क्रिप्ट अंतिम रूप खो रही है, थोड़ी देर बाद ठीक हो जाएगी। किया हुआ। –

3
एक्सएमएल की मदद से

:

INSERT INTO [dbo].[Words] 
SELECT DISTINCT [Word] 
FROM [dbo].[TempWords] 

DECLARE @xml xml 

SELECT @xml = (
    SELECT CAST('<row><word>'+WORD+'</word><w>' + REPLACE(WordForms,', ','</w><w>') +'</w></row>' as xml) 
    FROM [dbo].[TempWords] 
    FOR XML PATH('') 
    ) 


INSERT INTO [dbo].[WordForms] 
SELECT w.[WordId], 
     t.v.value('.','nvarchar(max)') as [Text] 
FROM @xml.nodes('/row/w') as t(v) 
LEFT JOIN [dbo].[Words] w 
    ON t.v.value('../word[1]','nvarchar(max)') = w.[Word] 

[dbo].[Words]

WordId Word 
1  abandon 
2  abstract 

में [dbo].[WordForms]

Id WordId Text 
1 1  abandoned 
2 1  abandoning 
3 1  abandonment 
4 1  abandons 
5 2  abstraction 
6 2  abstractions 
7 2  abstractly 
8 2  abstracts 
संबंधित मुद्दे