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

एसक्यूएल में स्ट्रिंग से चार, डबल, इंट पैटर्न पढ़ें

अंतिम संस्करण (मुझे आशा है):

चूंकि एसक्यूएल सर्वर 2008 कुल कार्यों के ओवर क्लॉज में ऑर्डर का समर्थन नहीं करता है, इसलिए मैंने sum के बजाय पंक्ति अनुक्रमणिका जोड़ने के लिए एक और सीटीई जोड़ा है मैंने पिछले संस्करण में उपयोग किया है:

;WITH cteAllRows as
(
     SELECT Item, 
            ItemIndex, 
            CASE WHEN ISNUMERIC(Item) = 0 THEN 'String'
            WHEN ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) > 0 THEN 'Double'
            WHEN ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) = 0 THEN 'Integer'
            END As DataType
     FROM dbo.SplitStrings_Numbers(@string, ',')
), cteAll as
(
    SELECT  Item, 
            DataType, 
            ItemIndex, 
            (
                SELECT COUNT(*)
                FROM cteAllRows tInner
                WHERE tInner.DataType = 'String'
                AND tInner.ItemIndex <= tOuter.ItemIndex
            ) As RowIndex
    FROM cteAllRows tOuter
)

बाकी सब पिछले संस्करण जैसा ही है।

अपडेट करें

पहली चीज जो मैंने की है वह है स्ट्रिंग स्प्लिट फंक्शन को टैली टेबल के आधार पर एक फंक्शन में बदलना, ताकि मैं इसमें आसानी से रो नंबर जोड़ सकूं। इसलिए, यदि आपके पास पहले से कोई मिलान तालिका नहीं है, एक बनाएं .अगर आप अपने आप से पूछ रहे हैं कि टैली टेबल क्या है और आपको इसकी आवश्यकता क्यों है, जेफ मोडेन का यह लेख पढ़ें :

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Tally
    FROM sys.objects s1       
    CROSS JOIN sys.objects s2 
ALTER TABLE Tally ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
GO

फिर, टैली टेबल के आधार पर स्ट्रिंग स्प्लिट फंक्शन बनाएं (हारून के लेख से लिया गया लेकिन पंक्ति इंडेक्स कॉलम जोड़ा गया):

CREATE FUNCTION dbo.SplitStrings_Numbers
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN
   (
       SELECT   Item = SUBSTRING(@List, Number, CHARINDEX(@Delimiter, @List + @Delimiter, Number) - Number),
                ROW_NUMBER() OVER (ORDER BY Number) As ItemIndex
       FROM dbo.Tally
       WHERE Number <= CONVERT(INT, LEN(@List))
         AND SUBSTRING(@Delimiter + @List, Number, LEN(@Delimiter)) = @Delimiter
   );
GO

अब, मैंने जिस ट्रिक का उपयोग किया है, वह पिछले वाले की तरह ही है, केवल अब मैंने पहले cte में एक नया कॉलम जोड़ा है जिसे मैंने RowIndex कहा है, जो मूल रूप से पंक्ति के आधार पर स्ट्रिंग्स की गिनती का कुल योग है। सभी पंक्तियों की अनुक्रमणिका:

 SELECT Item, 
        CASE WHEN ISNUMERIC(Item) = 0 THEN 'String'
        WHEN ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) > 0 THEN 'Double'
        WHEN ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) = 0 THEN 'Integer'
        END As DataType,
        SUM(CASE WHEN ISNUMERIC(Item) = 0 THEN 1 END) OVER(ORDER BY ItemIndex) As RowIndex
 FROM dbo.SplitStrings_Numbers(@string, ',')

इसने मुझे यह परिणाम दिया:

Item       DataType RowIndex
---------- -------- -----------
ddd        String   1
1.5        Double   1
1          Integer  1
eee        String   2
2.3        Double   2
0          Integer  2
fff        String   3
1.2        Double   3
ggg        String   4
6.123      Double   4
1          Integer  4

जैसा कि आप देख सकते हैं, मेरे पास अब प्रत्येक पंक्ति के लिए एक संख्या है, इसलिए अब से यह आसान है:

;WITH cteAll as
(
     SELECT Item, 
            CASE WHEN ISNUMERIC(Item) = 0 THEN 'String'
            WHEN ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) > 0 THEN 'Double'
            WHEN ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) = 0 THEN 'Integer'
            END As DataType,
            SUM(CASE WHEN ISNUMERIC(Item) = 0 THEN 1 END) OVER(ORDER BY ItemIndex) As RowIndex
     FROM dbo.SplitStrings_Numbers(@string, ',')
), cteString AS
(
    SELECT Item, RowIndex
    FROM cteAll
    WHERE DataType = 'String'
), cteDouble AS
(
    SELECT Item, RowIndex
    FROM cteAll
    WHERE DataType = 'Double'
), cteInteger AS
(
    SELECT Item, RowIndex
    FROM cteAll
    WHERE DataType = 'Integer'
)

SELECT  T1.Item As [String],
        T2.Item As [Double],
        T3.Item As [Integer]
FROM dbo.Tally 
LEFT JOIN cteString T1 ON T1.RowIndex = Number 
LEFT JOIN cteDouble T2 ON t2.RowIndex = Number 
LEFT JOIN cteInteger T3 ON t3.RowIndex = Number
WHERE COALESCE(T1.Item, T2.Item, T3.Item) IS NOT NULL

इसने मुझे यह परिणाम दिया:

String     Double     Integer
---------- ---------- ----------
ddd        1.5        1
eee        2.3        0
fff        1.2        NULL
ggg        6.123      1

जैसा कि आप देख सकते हैं, आइटम अब स्ट्रिंग में मूल क्रम के अनुसार क्रमबद्ध हैं। चुनौती के लिए धन्यवाद, यह कुछ समय हो गया है जब से मेरे पास एक अच्छा है :-)

पहला प्रयास

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

इस प्रदर्शन के लिए मैंने SplitStrings_XML . का उपयोग करना चुना है ।

तो सबसे पहले, फंक्शन बनाएं:

CREATE FUNCTION dbo.SplitStrings_XML
(
   @List       NVARCHAR(MAX),
   @Delimiter  NVARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
   RETURN 
   (  
      SELECT Item = y.i.value('(./text())[1]', 'nvarchar(4000)')
      FROM 
      ( 
        SELECT x = CONVERT(XML, '<i>' 
          + REPLACE(@List, @Delimiter, '</i><i>') 
          + '</i>').query('.')
      ) AS a CROSS APPLY x.nodes('i') AS y(i)
   );
GO

अब, वेरिएबल घोषित करें और इनिशियलाइज़ करें:

declare @string nvarchar(max) = 'ddd,1.5,1,eee,2.3,0,fff,1.2,ggg,6.123,1'

फिर, 4 सामान्य तालिका भाव बनाएं - सभी वस्तुओं के लिए एक, स्ट्रिंग्स के लिए एक, डबल्स के लिए एक और पूर्णांकों के लिए एक। row_number() के इस्तेमाल पर ध्यान दें फ़ंक्शन - इसका उपयोग बाद में सभी परिणामों को एक साथ जोड़ने के लिए किया जाएगा:

;WITH AllItems as
(
    SELECT Item, ROW_NUMBER() OVER(ORDER BY (select null)) as rn
    FROM dbo.SplitStrings_XML(@string, ',')
)

, Strings as
(
    SELECT Item as StringItem, ROW_NUMBER() OVER(ORDER BY (select null))  as rn
    FROM dbo.SplitStrings_XML(@string, ',')
    WHERE ISNUMERIC(Item) = 0
), Doubles as 
(
    SELECT Item as DoubleItem, ROW_NUMBER() OVER(ORDER BY (select null))  as rn
    FROM dbo.SplitStrings_XML(@string, ',')
    WHERE ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) > 0
), Integers as
(
    SELECT Item as IntegerItem, ROW_NUMBER() OVER(ORDER BY (select null))  as rn
    FROM dbo.SplitStrings_XML(@string, ',')
    WHERE ISNUMERIC(Item) = 1 AND CHARINDEX('.', Item) = 0 
)

फिर, इन सभी सामान्य तालिका अभिव्यक्तियों में शामिल होने से चुनें। COALESCE के इस्तेमाल पर ध्यान दें फ़ंक्शन में केवल उन पंक्तियों को वापस करने के लिए बनाया गया है जहां कम से कम एक मान मौजूद है:

SELECT StringItem,  DoubleItem, IntegerItem
FROM AllItems A
LEFT JOIN Strings S ON A.rn = S.rn
LEFT JOIN Doubles D ON A.rn = D.rn
LEFT JOIN Integers I ON A.rn = I.rn
WHERE COALESCE(StringItem,  DoubleItem, IntegerItem) IS NOT NULL

परिणाम:

StringItem  DoubleItem  IntegerItem
----------  ----------  -----------
ddd         1.5         1
eee         2.3         0
fff         1.2         1
ggg         6.123       NULL


  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. मैं VARBINARY (MAX) फ़ील्ड वाली तालिका के लिए INSERT स्क्रिप्ट कैसे उत्पन्न कर सकता हूं?

  3. तालिका के नाम + DDMMYYYY में कुछ तालिकाओं का नाम बदलें

  4. एकल कॉलम मानों को एकाधिक कॉलम मानों में कैसे विभाजित करें?

  5. SQL सर्वर में किसी निर्दिष्ट स्थान पर सूची आइटम कैसे खोजें