SQL用于数值的字符串操作

时间:2017-11-07 23:23:11

标签: sql sql-server string

我正在尝试编写一个sql查询,用于对2列进行字符串操作。

所以基本上目标是,对于2个不同列的值,如果数字的长度相同且两个符号相反,我必须从左边开始放下无关紧要的数字。这是一个帮助它变得清晰的例子。

如果我有2个数字,比方说1123457和-1124678,则查询应该返回3457和-4678。我有一个函数来做到这一点,但它似乎永远需要,因为那是逐行进行字符串操作。有没有人有这方面的经验?如果是这样,你能帮忙吗?

由于

2 个答案:

答案 0 :(得分:0)

您可以使用ABS功能代替用空字符串替换“ - ”吗?我觉得这样会更快。

https://docs.microsoft.com/en-us/sql/t-sql/functions/abs-transact-sql

答案 1 :(得分:0)

首先,在决定编写一些复杂逻辑时,您需要找出可用的工具。处理数字的字符串操作应该会引起所有语言的代码异味警报。

您可以在此处阅读各种SQL Server功能: https://docs.microsoft.com/en-us/sql/t-sql/functions/mathematical-functions-transact-sql

您还可以在互联网上搜索解决方案。我不得不搜索“sql server查找数字中的位数”来查找这篇文章: Counting the number of digits in column

代码:

DECLARE @Sample TABLE ( Num1 INT, Num2 INT )
INSERT INTO @Sample
VALUES( 1123457, -1124678 ), ( -1223457, 1124678 ), ( -1223457, -1124678 ), ( 0, 0 )

;WITH Step1 AS(
    -- Determine Number properties
    SELECT Num1, Num2, ABS( Num1 ) AS Num1Abs, ABS( Num2 ) AS Num2Abs,
        SIGN( Num1 ) AS Num1Sign,
        SIGN( Num2 ) AS Num2Sign,
        ( CASE WHEN LEN( ABS( Num1 )) = LEN( ABS( Num2 )) THEN 1 ELSE 0 END ) AS LenMatchFlag
    FROM @Sample 
),
Step2 AS(
    -- Find all possible significant digit matches of two numbers
    SELECT Num1, Num2, Num1Abs, Num2Abs, Num1Sign, Num2Sign, NumDigits,
        ROW_NUMBER() OVER( PARTITION BY Num1Abs, Num2Abs ORDER BY NumDigits ASC ) AS BestMatch
    FROM Step1
        -- Possible number of significant digits
        CROSS JOIN (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9)) AS NumLengths(NumDigits)
    WHERE 
        LenMatchFlag = 1
        AND Num1Sign = Num2Sign * -1 AND Num1Sign <> 0
        AND ROUND( Num1Abs, -NumDigits, 1 ) = ROUND( Num2Abs, -NumDigits, 1 )
),
Step3 AS(
    -- Return the best match, and calculate outpu values
    SELECT (( Num1Abs - ROUND( Num1Abs, -NumDigits, 1 )) * Num1Sign ) AS NewNum1,
        (( Num2Abs - ROUND( Num2Abs, -NumDigits, 1 )) * Num2Sign ) AS NewNum2,
        *
    FROM Step2
    WHERE BestMatch = 1
)
SELECT 'Changed', NewNum1, NewNum2, Num1, Num2
FROM Step3
UNION ALL
SELECT 'UnChanged', Num1, Num2, Num1, Num2
FROM Step1
WHERE NOT(
    LenMatchFlag = 1
    AND Num1Sign = Num2Sign * -1 AND Num1Sign <> 0
    )

输出:

          NewNum1     NewNum2     Num1        Num2
--------- ----------- ----------- ----------- -----------
Processed 3457        -4678       1123457     -1124678
Processed -223457     124678      -1223457    1124678
UnChanged -1223457    -1124678    -1223457    -1124678
UnChanged 0           0           0           0

注意:如果您的号码超过9位,则需要向NumLengths列表中添加更多值

注2:要查看每个计算步骤返回的值,您可以更改上一个SELECT以返回特定的表格,例如SELECT * FROM Step1