Tsql SQL 2017-在某些值可以为空的两个表之间比较值

Tsql SQL 2017-在某些值可以为空的两个表之间比较值,tsql,compare,common-table-expression,sql-server-2017,not-exists,Tsql,Compare,Common Table Expression,Sql Server 2017,Not Exists,我有以下表格和以下数据: CREATE TABLE TestSource ( InstrumentID int, ProviderID int, KPI1 int, Col2 varchar(255), KPI3 int ); CREATE TABLE TestTarget ( InstrumentID int, ProviderID int, KPI1 int, Col2 varchar(255), KP

我有以下表格和以下数据:

CREATE TABLE TestSource (
    InstrumentID int,
    ProviderID int,
    KPI1 int,
    Col2 varchar(255),
    KPI3 int
    );

CREATE TABLE TestTarget (
    InstrumentID int,
    ProviderID int,
    KPI1 int,
    Col2 varchar(255),
    KPI3 int 
    );

INSERT INTO TestSource (InstrumentID,ProviderID,KPI1,Col2,KPI3)
VALUES  (123, 27, 1, 'ABC', 10.0 ),
            (1234, 27, 2, 'DEF', 10.0 ),
            (345, 27, 1, NULL, 0.00 );

INSERT INTO TestTarget (InstrumentID,ProviderID,KPI1,Col2,KPI3)
VALUES  (123, 27, 1, 'ABC', 10.0 ),
            (1234, 27, 2, 'DEF', 10.0 ),
            (345, 27, 1, 'ABC', 0.0 );
我试图比较表之间的值。以下是我当前使用的查询逻辑:

DECLARE @Result NVARCHAR(max)

;WITH 

compare_source (InstrumentID,ProviderID,

/*** Source columns to compare ***/

            Col1Source, Col2Source,Col3Source

)

as (

              select     InstrumentID
                        ,ProviderID
                        ,KPI1
                        --,ISNULL(Col2,'NA') as Col2
                        ,Col2
                        ,KPI3

              from TestSource

              group by
                         InstrumentID
                        ,ProviderID
                        ,KPI1
                        ,Col2
                        ,KPI3
),

compare_target (InstrumentID,ProviderID,

/*** Target columns to compare ***/

            Col1Target,Col2Target,Col3Target

)

as 

(
            select
                     InstrumentID
                    ,ProviderID
                    ,KPI1
                    --,1
                    ,Col2
                    ,KPI3


            from TestTarget

            group by

                     InstrumentID
                    ,ProviderID
                    ,KPI1
                    ,Col2
                    ,KPI3
)

    SELECT @Result = STRING_AGG ('InstrumentID = ' + CONVERT(VARCHAR,InstrumentID)

         + ', Col1: ' + CONVERT(VARCHAR,Col1Source) + ' vs ' + CONVERT(VARCHAR,Col1Target)

        + ', Col2: ' + CONVERT(VARCHAR,Col2Source) + ' vs ' + CONVERT(VARCHAR,Col2Target)

        + ', Col3: ' + CONVERT(VARCHAR,Col3Source) + ' vs ' + CONVERT(VARCHAR,Col3Target) 

    , CHAR(13) + CHAR(10)

    )

FROM 
(
            select 
                     s.InstrumentID
                    ,s.Col1Source
                    ,t.Col1Target
                    ,s.Col2Source
                    ,t.Col2Target
                    ,s.Col3Source
                    ,t.Col3Target 

            from compare_source s

            left join compare_target t on t.InstrumentID = s.InstrumentID and t.ProviderID = s.ProviderID

            where not exists

            (
               select 1 from compare_target t where

                s.InstrumentID = t.InstrumentID AND 
              ( s.Col1Source   = t.Col1Target ) OR (ISNULL(s.Col1Source, t.Col1Target) IS NULL)  AND
              ( s.Col2Source   = t.Col2Target ) OR (ISNULL(s.Col2Source, t.Col2Target) IS NULL)  AND
              ( s.Col3Source   = t.Col3Target ) OR (ISNULL(s.Col3Source, t.Col3Target) IS NULL) 
        )

) diff

PRINT @Result
当我的表中没有空值时,比较效果很好。但是,只要我尝试在两个表中插入空值,我的比较逻辑就会崩溃,并且不会考虑表值之间的差异

我知道我可以很容易地在我的个人选择中对我的列执行ISNULL,但是,我希望尽可能地保持它的通用性,并且只在我的最终notexists comparison WHERE子句中执行比较检查和NULL检查

我还在比较逻辑中尝试了以下逻辑,但没有成功:

            (
                   select 1 from compare_target t where

                    s.InstrumentID = t.InstrumentID AND 
                  ( s.Col1Source   = t.Col1Target OR (s.Col1Source IS NULL AND t.Col1Target IS NULL) ) AND
                  ( s.Col2Source   = t.Col2Target OR (s.Col2Source IS NULL AND t.Col2Target IS NULL) ) AND
                  ( s.Col3Source   = t.Col3Target OR (s.Col3Source IS NULL AND t.Col3Target IS NULL) )
            )
我遇到的另一个问题是,我的查询无法区分数据格式,例如,它认为值0.00等同于0.0

我不能完全肯定我错过了什么


任何能让我走上正确道路的帮助都会很好。

我看到的两个问题是:

底部的WHERE子句需要有额外的括号,以便将OR与AND组合在一起,以便优先级顺序正确:

  select 1 from compare_target t where

    s.InstrumentID = t.InstrumentID AND 
  (( s.Col1Source   = t.Col1Target ) OR (ISNULL(s.Col1Source, t.Col1Target) IS NULL))  AND
  (( s.Col2Source   = t.Col2Target ) OR (ISNULL(s.Col2Source, t.Col2Target) IS NULL))  AND
  (( s.Col3Source   = t.Col3Target ) OR (ISNULL(s.Col3Source, t.Col3Target) IS NULL)) 
进行更改时,返回的一行在Col2Source列中具有空值。因此,当您尝试构建您发送到String AGG的字符串时,它中间有一个NULL。所以整个字符串将为空。因此,您需要在FROM子句中的子查询中或字符串_AGG…中使用ISNULL,或者在注释掉它的地方使用ISNULL


另外,我没有输入我的答案,但是您输入到KPI3中的值是小数,并且您将此字段定义为INT。因此,您将丢失小数后的任何内容。因此0.00=0.0,因为它只是0=0。非常感谢您的输入!我会检验你的建议,并让你知道。吉咪,你的建议行得通!!非常感谢。在比较0.0和0.00格式值方面,有一件小事。。。我假设我需要明确地将我的专栏放在每一边?我在原来的问题上添加了一条评论。但是您已经将该列定义为INT。因此,如果您想在其中保留一个小数,则必须将该列定义为小数。对不起,我刚才看到了您的注释。一切都好!!非常感谢!