【问题标题】:How to perform lookup based on column header name?如何根据列标题名称执行查找?
【发布时间】:2021-01-18 00:17:20
【问题描述】:

希望有人可以协助构建以下查询。

代码类型

Code |  ID  | Type
---------------------
ABC  | 1234 | 'Type1'
ABC  | 1234 | 'Type2'
CDE  | 2345 | 'Type1'
CDE  | 2345 | 'Type3'
EFG  | 3456 | 'Type2'

类型值

Code |  ID  |  Type1  |  Type2  |  Type3
----------------------------------------
ABC  | 1234 | ';kjap' | ')&jaa' | '123ja' 
CDE  | 2345 |   NULL  | '$@#$a' | 'asdfa'
EFG  | 3456 | '&*(01' | 'jmblk' |   NULL

我希望能够构造尾随列“TypeValue”,它本质上是基于TypeValues 表中TypeValues 中特定TypeCodeID 查找。

Code |  ID  |  Type   |  TypeValue
----------------------------------
ABC  | 1234 | 'Type1' |  ';kjap' 
ABC  | 1234 | 'Type2' |  ')&jaa'
CDE  | 2345 | 'Type1' |   NULL
CDE  | 2345 | 'Type3' |  'asdfa'
EFG  | 3456 | 'Type2' |  'jmblk'

【问题讨论】:

    标签: sql-server tsql pivot


    【解决方案1】:

    您可以使用CASE 选择要使用的列。例如:

    select
      t.*,
      case when t.type = 'Type1' then v.type1
           when t.type = 'Type2' then v.type2
           when t.type = 'Type3' then v.type3
      end as typevalue
    from codetypes t
    join typevalues v on v.code = t.code and v.id = t.id
    

    根据 HABO 的评论进行编辑

    查询可以进一步简化为:

    select
      t.*,
      case t.type when 'Type1' then v.type1
                  when 'Type2' then v.type2
                  when 'Type3' then v.type3
      end as typevalue
    from codetypes t
    join typevalues v on v.code = t.code and v.id = t.id
    

    【讨论】:

    • 或者使用simple CASE expression,而不是搜索,因为它针对多个值测试一个表达式(t.type):case t.type when 'Type1' then v.type1 when 'Type2' then v.type2 when 'Type3' then v.type3 end
    【解决方案2】:

    首先:如果你可以改变设计,你应该这样做。每当您觉得需要 name-number 列(Type1、Type2...)时,这都是糟糕的设计。

    寻找一个完全通用的方法你可以试试这个:

    DECLARE @CodeTypes TABLE(Code VARCHAR(100),ID INT,[Type] VARCHAR(100));
    DECLARE @TypeValues TABLE(Code VARCHAR(100),ID INT,Type1 VARCHAR(100),Type2 VARCHAR(100),Type3 VARCHAR(100))
    
    INSERT INTO @CodeTypes(Code,ID,[Type]) VALUES
     ('ABC',1234,'Type1')
    ,('ABC',1234,'Type2')
    ,('CDE',2345,'Type1')
    ,('CDE',2345,'Type3')
    ,('EFG',3456,'Type2');
    
    INSERT INTO @TypeValues(Code,ID,Type1,Type2,Type3) VALUES
     ('ABC',1234,';kjap',')&jaa','123ja') 
    ,('CDE',2345,  NULL ,'$@#$a','asdfa')
    ,('EFG',3456,'&*(01','jmblk',  NULL );
    

    --查询

    SELECT ct.Code
          ,ct.ID,ct.[Type]
          ,(SELECT tv.* FOR XML PATH(''),TYPE)
           .value('(*[local-name()=sql:column("Type")]/text())[1]','varchar(100)') TypeValue  
    FROM @CodeTypes ct
    INNER JOIN @TypeValues tv ON ct.ID=tv.ID
                             AND ct.Code=tv.Code;
    

    简而言之:

    • 我们使用简单的 JOIN 将两个表放在一起。
    • 神奇之处在于 XML 能够通过名称获取列。
    • 我们为结果集的每一行查询tv一行
    • 我们为行创建一个 XML 并通过 local-name() 谓词选择一个值。

    提示:这不会很快,但是 - 如果您决定添加 Type4,您将不必重写现有查询...

    【讨论】:

    • 我同意你的观点——虽然速度不快——但这个解决方案可以灵活。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-20
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多