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

Sql server 从多个列中查询相同参数的智能代码?,sql-server,tsql,Sql Server,Tsql,我们有一个非常宽的表,其中有25个诊断代码列: diag1, diag2, … diag25. 如果我想查找诊断代码“12345”,我需要编写 diag1 ='12345' or diag2='12345' or diag3='12345'... or diag25='12345' 有没有办法做到这一点: diag1-diag25 ='12345' 实际上,所有这些diagxx列都应该在一个单独的表中。所以你的设计应该改变 如果您不能做到这一点,那么可以通过在where子句中使用IN使查询

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

diag1, diag2, … diag25.
如果我想查找诊断代码“12345”,我需要编写

diag1 ='12345' or diag2='12345' or diag3='12345'... or diag25='12345'
有没有办法做到这一点:

diag1-diag25 ='12345'
实际上,所有这些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   
这与您想要的语法非常接近,您可以编写

'12345' IN (diag1, diag2, ..., diag25)
但是diag1-diag25没有语法

另一种方法是将诊断代码解压到单个列中,然后查询结果数据集

有关取消激励选项的完整讨论,请参见此问题

使用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

编辑:根据注释添加了join/temp表。

另一种可能更灵活的解决方案是使用交叉应用取消数据的PIVOT:

输出:

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

您可以调用XML的通用功能来拯救您。梅排的速度不是很快,但很强大:

模型的制作归功于Dave

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将检查这些元素中是否有任何值位于您的边界之间。一场比赛就够了


祝你好运

你能重新设计你的数据表吗?这些诊断代码应该都在各自的行中。不是现在,可能是在多个决策者确定后的将来Wow不知道这是可能的。如果参数是介于“12349”之间的“12345”,又如何?这种查询方式调用的是什么?我试着用谷歌搜索列列表中的WHERE条件,但我不认为这个样式有任何特殊的名称——这只是语法@LeeY。您的问题是参数是否在“12349”之间为“12345”?这就是这种方法的局限性所在。不过,您可以使用更灵活的unpivot方法来执行此操作。@DenisRubashkin,是否有函数返回满足条件的第一列?例如,图1、图2、图3中的“12345”;哪栏有“12345”?我同意。不幸的是,办公室工作环境会让你的工作变得更容易,这可能是我必须要做的。虽然我无法在工作中得到中间陈述,但在何处,中间陈述是什么意思?你能解释一下你想做什么吗?像这样:在diag1、diag2、diag3中,在“12349”和“12345”之间,真正的业务场景是在C00和C96之间捕获70个诊断代码。我以为XML技巧是John Cappelletti的部门;-这是搜索一系列值的一个好选项+1.对答案和评论投赞成票,因为我一开始阅读,就以为是约翰。@ZoharPeled yeah@EricBrandt funnyup投我这边的票。可能是处理一组已知列名的最佳方法。还有thx给你做模型。我借了它作为我的答案。编辑了我的答案来解释搜索一堆诊断代码的原因。
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;