Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL-仅从包含字符串的列中选择数字_Sql_Sql Server_Sql Server 2008_Patindex_Charindex - Fatal编程技术网

SQL-仅从包含字符串的列中选择数字

SQL-仅从包含字符串的列中选择数字,sql,sql-server,sql-server-2008,patindex,charindex,Sql,Sql Server,Sql Server 2008,Patindex,Charindex,我有一个这样的表,第一列包含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(

我有一个这样的表,第一列包含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的函数:

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
其思想是首先用逗号替换所有数学字符:+、-、*、/、=,。这是必需的,以便我们以后可以拆分操作数。接下来调用splitter函数以使用逗号作为分隔符拆分行。拆分完成后,使用不相似的“[^0-9]%”和项筛选所有数值。您希望将此操作的结果插入临时表。然后,使用适当的WHERE子句从临时表中选择:


这是一个没有用户定义函数的解决方案。它应该快得多:

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

你知道如何使用.Net编写正则表达式吗?我认为CLR用户定义函数是实现这一点的方法。我只需要使用SQL server。。project requirement.CLR函数是SQL Server的一部分。这是一些疯狂的需求
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