Как сравнить данные из двух таблиц, используя операторы сравнения, хранящиеся в базе данных? - PullRequest
0 голосов
/ 28 мая 2019

Я ищу способ создания сценария для сравнения данных из двух разных таблиц, используя операторы сравнения, хранящиеся в базе данных.

Мне удалось решить двумя способами:

  1. с использованием динамического SQL
  2. с использованием операторов case

, но я хотел бы решить, используя что-то, что не включает динамический 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

Мне нужно сравнить данные между столбцами ComparisonValue и BaseValue на основе операторов сравнения, и ядолжен получить код предупреждения, который точно соответствует каждому из сравнений между ComparisonValue и BaseValue.

Будет ли какой-то способ добиться этого без использования динамического SQL или оператора case?

1 Ответ

0 голосов
/ 28 мая 2019

Вы используете пилу, где вам нужен молоток. SQL предназначен для очень эффективного сохранения данных. Он не предназначен для этого. Вы должны изучить C # или Java. Это можно сделать очень легко на правильном языке.

Однако, если вы должны использовать SQL, вы должны создать процедуру для каждого сравнения. Procs должен взять данные двух сравниваемых вами значений. Таким образом, вся логика такого сравнения содержится в его собственной маленькой капсуле.

Вызовите процесс, который вы хотите, динамически, выбрав Имя процесса, которое вы поместите в таблицу с операторами сравнения.

Если вы хотите сделать «>», то вызов «GreaterThan» будет вызываться при передаче значений для сравнения.

Если вы хотите сделать это более эффективным, создайте типы таблиц для типов вещей, которые вы будете сравнивать, а затем передайте целый список элементов за раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...