簡體   English   中英

SQL-僅從包含字符串的列中選擇數字

[英]SQL- select only numbers from column which contains string

我有一個這樣的表(第一列包含id和第二列是varchar,其中包含字符串(某些公式))-

column_id       column_formula
4686         4686 = 4684 - 4685 
4687         4687 = ( 4681 / 1.205 / 4684 * 1000 ) 
4717         4717 = ( 4711 + 4712 + 4713 + 4714 + 4715 + 4716 )/6 
4719         4719 = abs( 4716 - 4715 ) 
4787         4787 = max(max(max(max(max( 4780 , 4781 ), 4782 ), 4783 ), 4784 ), 4785 ) - min(min(min(min(min( 4780 , 4781 ), 4782 ), 4783 ), 4784 ), 4785 ) 

現在需要一些查詢,它將給出如下輸出:

col1    col2
4686    4684      
4686    4685      
4687    4681 
4687    4684 
4717    4711
4717    4712

依此類推(僅限於小於4位數字的數字,如1.205左右的..和1000)。

在這一點上很難使用patindex

任何人都可以給我解決方案嗎

您需要具有一個將逗號分隔的字符串拆分為單獨的行的功能。 這是Jeff Moden的DelimitedSplit8K函數:

CREATE FUNCTION [dbo].[DelimitedSplit8K](
    @pString NVARCHAR(4000), @pDelimiter NCHAR(1)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
,E2(N) AS (SELECT 1 FROM E1 a, E1 b)
,E4(N) AS (SELECT 1 FROM E2 a, E2 b)
,cteTally(N) AS(
    SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
)
,cteStart(N1) AS(
    SELECT 1 UNION ALL 
    SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
),
cteLen(N1,L1) AS(
SELECT 
    s.N1,
    ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
FROM cteStart s
)
SELECT 
    ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
    Item       = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l

我們的想法是REPLACE首先數學字符: +- */()=用逗號, 這是必需的,因此我們以后可以拆分操作數。 接下來調用分離器功能分割使用逗號行,作為分隔符。 拆分完成后,請使用NOT LIKE '[^0-9]%' AND Item <> ''過濾所有數值。 您想將此結果INSERTTemp Table 然后,使用適當的WHERE子句從該Temp Table進行SELECT

;WITH cteSanitized AS(
    SELECT
        t.Column_Id,
        Item = 
            REPLACE(
                REPLACE(
                    REPLACE(
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        SUBSTRING(t.Column_Formula, CHARINDEX('=', t.Column_Formula), LEN(t.Column_Formula) - CHARINDEX('=', t.Column_Formula) + 1)
                                        ,'+',','
                                    ), '-',','
                                ), '/',','
                            ), '*',','
                        ), ')', ',)'
                    ), '(',','
                ), '=',','
            )
    FROM Test t
)
,CteSplitted AS(
    SELECT
        s.Column_Id,
        ItemNumber,
        Item = LTRIM(RTRIM(x.Item))
    FROM cteSanitized s
    CROSS APPLY dbo.DelimitedSplit8K(s.Item, ',') x
)
SELECT 
    Column_Id,
    ItemNumber,
    Item = CONVERT(NUMERIC, ITEM)
INTO #TempTable
FROM CteSplitted
WHERE 
    Item  NOT LIKE '[^0-9]%'
    AND Item <> ''

SELECT DISTINCT
    Col1 = Column_Id,
    Col2 = Item
FROM #TempTable
WHERE Item > 1000

DROP TABLE #TempTable

結果

Col1        Col2
----------- ---------
4686        4684
4686        4685
4687        4681
4687        4684
4717        4711
4717        4712
4717        4713
4717        4714
4717        4715
4717        4716
4719        4715
4719        4716
4787        4780
4787        4781
4787        4782
4787        4783
4787        4784
4787        4785

這是沒有用戶定義功能的解決方案。 它應該快得多:

DECLARE @t TABLE ( ID INT, F NVARCHAR(MAX) )

INSERT  INTO @t
VALUES  ( 4686, '4686 = 4684 - 4685' ),
        ( 4687, '4687 = ( 4681 / 1.205 / 4684 * 1000 )' ),
        ( 4717, '4717 = ( 4711 + 4712 + 4713 + 4714 + 4715 + 4716 )/6' ),
        ( 4719, '4719 = abs( 4716 - 4715 ) ' ),
        ( 4787,
          '4787 = max(max(max(max(max( 4780 , 4781 ), 4782 ), 4783 ), 4784 ), 4785 ) - min(min(min(min(min( 4780 , 4781 ), 4782 ), 4783 ), 4784 ), 4785 )' )

DECLARE @chars TABLE ( ID INT, c NVARCHAR(MAX) )
INSERT  INTO @chars
VALUES  ( 1, ' ' ),
        ( 2, '(' ),
        ( 3, ')' ),
        ( 4, '/' ),
        ( 5, '*' ),
        ( 6, '+' ),
        ( 7, '-' ),
        ( 8, 'max' ),
        ( 9, 'min' ),
        ( 10, 'abs' ),
        ( 11, '=' )

DECLARE @count INT
SELECT  @count = COUNT(*) FROM    @chars;

WITH    recursion
          AS ( SELECT   t.ID ,
                        REPLACE(F, ' ', ',') + ',' AS F ,
                        1 AS CharID
               FROM     @t t
               UNION ALL
               SELECT   t.ID ,
                        REPLACE(t.F, c.c, ',') AS F ,
                        t.CharID + 1 AS CharID
               FROM     recursion t
                        JOIN @chars c ON c.ID = t.CharID + 1
               WHERE    t.CharID < @count
             ),
        commastrings
          AS ( SELECT   ID ,
                        STUFF(F, LEN(F), 1, '') AS F
               FROM     ( SELECT    ID ,
                                    REPLACE(REPLACE(REPLACE(F, ',', '{}'), '}{', ''), '{}', ',') AS F
                          FROM      recursion
                          WHERE     CharID = @count
                        ) a
             ),
        final ( ID, Number, rght, idx )
          AS ( SELECT   t.ID ,
                        LEFT(t.F, CHARINDEX(',', t.F) - 1) ,
                        SUBSTRING(t.F, CHARINDEX(',', t.F) + 1, LEN(t.F)) ,
                        0
               FROM     commastrings t
               UNION ALL
               SELECT   c.id ,
                        CASE WHEN CHARINDEX(',', c.rght) = 0 THEN c.rght
                             ELSE LEFT(c.rght, CHARINDEX(',', c.rght) - 1)
                        END ,
                        CASE WHEN CHARINDEX(',', c.rght) > 0
                             THEN SUBSTRING(c.rght, CHARINDEX(',', c.rght) + 1, DATALENGTH(c.rght))
                             ELSE ''
                        END ,
                        idx + 1
               FROM     final c
               WHERE   LENGTH(c.rght) > 0
             )
    SELECT DISTINCT
            ID ,
            Number
    FROM    final
    WHERE   idx <> 0
            AND CAST(Number AS DECIMAL(20, 10)) > 1000

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM