如何使用存储在数据库中的比较运算符比较两个表中的数据?

时间:2019-05-28 18:52:56

标签: sql sql-server

我正在寻找一种使用存储在数据库中的比较运算符来构建脚本来比较两个不同表中数据的方法。

我通过两种方式解决:

  1. 使用动态SQL
  2. 使用案例陈述

但是我想解决不使用动态SQL或case语句的问题。

这是我的基本数据表:

    create table #BaseData
    (
        ID int identity (1,1),
        numR int,
        ALertCode varchar (10),
        numOp     int,
        BaseOrder int,
        Criteri varchar (50),
        Operator varchar (5),
        BaseValue int
    )

    insert into #BaseData (numR, AlertCode, numOp, BaseOrder, Criteri, Operator, BaseValue)
    select 
    ROW_NUMBER() over (order by (select null)) numR,    ALertCode, 
    ROW_NUMBER() over (partition by ALertCode order by AlertCode )numOp,
    DatosBase.BaseOrder, Criteri,           Operator, DatosBase.ComparisonValue BaseValue 
    from 
    (             select    'A_1_<1000 ' ALertCode , 1  BaseOrder, 'ES_CV_Basal                 'Criteri,   '='     Operator,    1     ComparisonValue
        union all select    'A_1_<1000 ' ALertCode , 2  BaseOrder, 'Carga_Viral_Basal           '        ,  '='             ,    19 
        union all select    'A_1_<1000 ' ALertCode , 3  BaseOrder, 'Dias_CargaViralActual       '        ,  NULL            ,    NULL 
        union all select    'A_1_<1000 ' ALertCode , 4  BaseOrder, 'Carga_Viral_VIH_Previa_01   '        ,  NULL            ,    NULL 
        union all select    'A_1_<1000 ' ALertCode , 5  BaseOrder, 'ES_CV_Basal_01              '        ,  NULL            ,    NULL 
        union all select    'A_1_<1000 ' ALertCode , 6  BaseOrder, 'Carga_Viral_VIH_Previa_02   '        ,  NULL            ,    NULL 
        union all select    'A_1_<1000 ' ALertCode , 7  BaseOrder, 'DiasCVPrevia_02             '        ,  NULL            ,    NULL 
        union all select    'A_1_<1000 ' ALertCode , 8  BaseOrder, 'Dif_CVe_CVp'                         ,  NULL            ,    NULL 
        union all                                                                                    
                  select    'A_2_<1000'  ALertCode , 1  BaseOrder, 'ES_CV_Basal                 '        ,  '='             ,   1        
        union all select    'A_2_<1000'  ALertCode , 2  BaseOrder, 'Carga_Viral_VIH             '        ,  '>'             ,   1000    
        union all select    'A_2_<1000'  ALertCode , 3  BaseOrder, 'Dias_CargaViralActual       '        ,  NULL            ,   NULL    
        union all select    'A_2_<1000'  ALertCode , 4  BaseOrder, 'Carga_Viral_VIH_Previa_01   '        ,  NULL            ,   NULL    
        union all select    'A_2_<1000'  ALertCode , 5  BaseOrder, 'TDias_01                    '        ,  NULL            ,   NULL    
        union all select    'A_2_<1000'  ALertCode , 6  BaseOrder, 'Carga_Viral_VIH_Previa_02   '        ,  NULL            ,   NULL    
        union all select    'A_2_<1000'  ALertCode , 7  BaseOrder, 'TDias_02                    '        ,  NULL            ,   NULL    
        union all select    'A_2_<1000'  ALertCode , 8  BaseOrder, 'Dif_CVe_CVp'                         ,  NULL            ,   NULL 
        union all                                                                                    
                  select    'A_1000'  ALertCode , 1     BaseOrder, 'ES_CV_Basal                 '        ,  NULL            ,   NULL        
        union all select    'A_1000'  ALertCode , 2     BaseOrder, 'Carga_Viral_VIH             '        ,  '>='            ,   1000        
        union all select    'A_1000'  ALertCode , 3     BaseOrder, 'Dias_CargaViralActual       '        ,  '>='            ,   168     
        union all select    'A_1000'  ALertCode , 4     BaseOrder, 'Carga_Viral_VIH_Previa_01   '        ,  '='             ,   19      
        union all select    'A_1000'  ALertCode , 5     BaseOrder, 'TDias_01                    '        ,  '>='            ,   168     
        union all select    'A_1000'  ALertCode , 6     BaseOrder, 'Carga_Viral_VIH_Previa_02   '        ,  NULL            ,   NULL        
        union all select    'A_1000'  ALertCode , 7     BaseOrder, 'TDias_02                    '        ,  NULL            ,   NULL        
        union all select    'A_1000'  ALertCode , 8     BaseOrder, 'Dif_CVe_CVp'                         ,  NULL            ,   NULL                                                                                                         
    )BaseData
    order by ALertCode, BaseOrder

这是我的比较数据表:

    create table #ComparisonData 
    (
      ID int identity (1,1),
      ComparisonOrder int, 
      EvaluationCriteri varchar(50),
      ComparisonValue decimal (10,6)
    )

    insert into #ComparisonData  (ComparisonOrder, EvaluationCriteri, ComparisonValue)
    select ComparisonOrder, EvaluationCriteri, ComparisonValue
    from        
    (             select 1  ComparisonOrder,    'ES_CV_Basal'   EvaluationCriteri, 2        ComparisonValue
        union all select 2       ,  'Carga_Viral_VIH'   EvaluationCriteri, 1001     ComparisonValue
        union all select 3       ,  'TDias'             EvaluationCriteri, 169      ComparisonValue
        union all select 4       ,  'Carga_Viral_VIH'   EvaluationCriteri, 19       ComparisonValue
        union all select 5       ,  'TDias'             EvaluationCriteri, 169      ComparisonValue
        union all select 6       ,  'Carga_Viral_VIH'   EvaluationCriteri, 387      ComparisonValue
        union all select 7       ,  'TDias'             EvaluationCriteri, 265      ComparisonValue
        union all select 8       ,  'Dif_CVe_CVp'       EvaluationCriteri, -0.33    ComparisonValue
    )ComparisonData

这是我用来比较数据的表:

    create table #AlertDetected 
    (
        ID int identity (1,1),
        numR int, 
        AlertCode   varchar (10), 
        numOp       int, 
        BaseOrder   int, 
        Criteri varchar(50), 
        Operator    varchar(5), 
        BaseValue   int,
        ComparisonOrder     int,
        EvaluationCriteri varchar (50),
        ComparisonValue decimal(10,6)
    )


    insert into #AlertDetected (numR, AlertCode, numOp, BaseOrder, Criteri, Operator, BaseValue, ComparisonOrder,   EvaluationCriteri, ComparisonValue)
    select  ROW_NUMBER() over (order by (select null)) numR, ALertCode, 
            ROW_NUMBER() over (partition by ALertCode order by AlertCode )numOp,
                                                                            BaseOrder, Criteri, Operator, BaseValue, dc.ComparisonOrder,EvaluationCriteri, ComparisonValue
    from #BaseData db
    left join #ComparisonData  dc
    on db.BaseOrder = dc.ComparisonOrder
    where db.BaseValue is not null 

这是我的动态SQL解决方案:

    select  'select max(AlertResult)AlertResult  from ( ' + stuff(( select 'union all' + Operacion
    from 
    (   select   stuff(( select  +  concat (   ' ' , Operacion)
        from
        (   
            select numR, AlertCode,   BaseOrder,   concat (iif (numOp = 1 , '  select iif(  ', '  and  ' ),  ComparisonValue  ,  Operator , ' ', BaseValue)Operacion
            from 
            ( select numR, AlertCode,   BaseOrder, numOp , BaseValue ,  Operator ,  case when numOp<> 8 then floor( ComparisonValue ) else  cast ( ComparisonValue as float ) end ComparisonValue -- 
              from #AlertDetected 
            )t  
        )x
        where x.AlertCode =  isc.AlertCode FOR XML PATH(''), TYPE ).value('.[1]', 'varchar(max)'), 1, 1, '')  + '  ,  '+''''+AlertCode+''''+ ', '+ ''''+'0'+ '''' + ' )   AlertResult   '   as Operacion
        from #AlertDetected  isc group by AlertCode      
    )X
    FOR XML PATH(''), TYPE ).value('.[1]', 'varchar(max)'), 1, 9, '')  + ' ) Datos'as CamposInforme 

这是我的案例陈述解决方案:

select  iif (sum(Result)  = row_count , AlertCode, ' ')AlertDetected
from
( select  numR, AlertCode, numOp, BaseOrder, Criteri, ComparisonValue, Operator, BaseValue,                         
                    case    when Operator ='=' then iif (ComparisonValue = BaseValue, 1,0) 
                            when Operator ='<' then iif (ComparisonValue < BaseValue, 1,0) 
                            when Operator ='>' then iif (ComparisonValue > BaseValue, 1,0) 
                            when Operator ='>=' then iif (ComparisonValue >= BaseValue, 1,0) 
                            when Operator ='<=' then iif (ComparisonValue <= BaseValue, 1,0)  end Result , row_count
    from 
    (   select  numR, a.AlertCode, Criteri,  BaseOrder, numOp , BaseValue ,  Operator ,  
                case when numOp<> 8 then floor( ComparisonValue ) else  cast ( ComparisonValue as float ) end ComparisonValue , c.row_count 
        from #AlertDetected  a
        inner join 
    (       select AlertCode, COUNT(*) AS row_count
            FROM dbo.#AlertDetected 
            group by  AlertCode
        )c on a.AlertCode = c.AlertCode
    )d  
)d  group by AlertCode, row_count

我需要基于比较运算符比较CompareValue和BaseValue列之间的数据,并且我必须获取完全符合CompareValue和BaseValue之间的每个比较的警报代码。

有一些方法可以实现,而无需使用动态SQL或case语句?

1 个答案:

答案 0 :(得分:0)

您在需要使用锤子的地方使用了锯。 SQL旨在非常有效地持久化数据。它不是为此设计的。 您应该学习C#或Java。用适当的语言可以很容易地做到这一点。

但是,如果必须使用SQL,则应该为每个比较创建一个proc。 proc应该接受您正在比较的两个值的输入。这样,进行一次比较的所有逻辑都包含在自己的小胶囊中。

通过选择要与比较运算符一起放在表中的proc名称,动态调用所需的proc。

如果您想执行“>”,那么当您传递要比较的值时,将调用“ GreaterThan”过程。

如果要提高效率,请为要比较的事物创建表类型,然后一次传递整个项目列表。