从多个列中查询相同参数的更智能代码?

时间:2018-10-04 13:02:41

标签: sql-server tsql

我们有一个非常宽的表,其中包含25个诊断代码列:

XTemplate

如果我要查找诊断代码'12345',我需要写

diag1, diag2, … diag25.

有没有办法做这样的事情:

diag1 ='12345' or diag2='12345' or diag3='12345'... or diag25='12345'

5 个答案:

答案 0 :(得分:4)

你可以写

'12345' IN (diag1, diag2, ..., diag25)

但是diag1-diag25没有语法

答案 1 :(得分:3)

您可以将XML的通用功能称为抢救。可能行数不是很快,但是非常强大:

(向iamdave致谢)

declare @t table(id int,diag1 int,diag2 int,diag3 int,diag4 int,diag5 int,diag6 int,diag7 int,diag8 int,diag9 int,diag10 int);
insert into @t (id, diag5) values(1,12345);
insert into @t (id, diag3) values(2,123);
insert into @t (id, diag8, diag1) values(3,123,12345);
insert into @t (id, diag9, diag2) values(4,345,678);

WITH CreateXML AS
(
    SELECT * 
          ,(
            SELECT *
            FROM @t t2
            WHERE t1.id=t2.id
            FOR XML PATH('codes'),TYPE
           ).query('/codes/*[substring(local-name(),1,4)="diag"]') AllCodes
     FROM @t t1 
)
SELECT * 
FROM CreateXML
WHERE AllCodes.exist('/*[. cast as xs:int? >=12345 and . cast as xs:int? <=12349]')=1;

查询将使用SELECT *创建所有列的XML。 .query()将选择以"diag"开头的所有元素。也许您必须对此进行调整以适应您的需求。

.exist()将检查这些元素内的任何值是否在边界之间。一场比赛就足够了。

祝你好运!

答案 2 :(得分:2)

另一种可能更灵活的解决方案是使用cross apply取消数据透视:

declare @t table(id int,diag1 int,diag2 int,diag3 int,diag4 int,diag5 int,diag6 int,diag7 int,diag8 int,diag9 int,diag10 int);
insert into @t (id, diag5) values(1,12345);
insert into @t (id, diag3) values(2,123);
insert into @t (id, diag8, diag1) values(3,123,12345);
insert into @t (id, diag9, diag2) values(4,345,678);

select t.id
      ,d.d
from @t as t
    cross apply(values(diag1),(diag2),(diag3),(diag4),(diag5),(diag6),(diag7),(diag8),(diag9),(diag10)) d(d)
where d.d = 12345;

输出:

+----+-------+
| id |   d   |
+----+-------+
|  1 | 12345 |
|  3 | 12345 |
+----+-------+

答案 3 :(得分:1)

实际上,所有这些diagxx列都应位于单独的表中。因此,您的设计应进行更改。

如果您无法执行此操作,则可以在where子句中使用IN,从而使查询更加轻松。

declare @d table (diag1 varchar(5), diag2 varchar(5), diag3 varchar(5))
insert into @d values ('12345', '23456', '34567'),
                      ('45678', '12345', '56789'),
                      ('45678', '85236', '56789')
select * 
from   @d
where  '12345' in (diag1, diag2, diag3)

这将返回

diag1   diag2   diag3   
-----   -----   -----   
12345   23456   34567   
45678   12345   56789   

这与您将要获得的语法非常接近

答案 4 :(得分:1)

另一种方法是将诊断代码UNPIVOT放在一列中,然后查询结果数据集。

有关取消固定选项的完整讨论,请参阅此问题。 SQL Server : Columns to Rows

使用varchar诊断代码,BETWEEN可能无法达到您想要的方式,但是您可以将70多种代码转储到临时表中并加入它。

但是遵循这些原则:

select * from 
(
  select 
    <Any Key Fields You Want To Include>,
    diagColumnName,
    diagCode
  from yourtable
  unpivot
  (
    diagCode
    for diagColumnName in (diag1, diag2....diag25)
  ) as unpiv
) as resultSet
join #tempCodes as t
  on t.diagCode = resultSet.diagCode

编辑:根据评论添加了联接/临时表。