Разумнее код для запроса одного и того же параметра из нескольких столбцов? - PullRequest
0 голосов
/ 04 октября 2018

У нас есть очень широкая таблица с 25 столбцами кодов диагностики:

diag1, diag2, … diag25.

Если я хочу найти код диагностики "12345", мне нужно написать

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

IsЕсть способ сделать что-то вроде этого:

diag1-diag25 ='12345'

Ответы [ 5 ]

0 голосов
/ 04 октября 2018

Вы можете использовать общие возможности 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() проверит, находится ли какое-либо значение в этих элементах между вашими границами.Достаточно одного матча.

Удачи!

0 голосов
/ 04 октября 2018

Альтернативное и потенциально более гибкое решение - отключить данные, используя 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 |
+----+-------+
0 голосов
/ 04 октября 2018

Вы можете написать

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

, но нет синтаксиса для diag1-diag25

0 голосов
/ 04 октября 2018

Другим способом будет UNPIVOT ваши диагностические коды в одном столбце, а затем запросить результирующий набор данных.

Полное обсуждение вариантов отмены ответов см. В этом вопросе. SQL Server: столбцы в строки

При 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

Редактировать : добавлена ​​таблица присоединения / температуры на основе комментариев.

0 голосов
/ 04 октября 2018

На самом деле все эти diagxx столбцы должны быть в отдельной таблице.Таким образом, ваш дизайн должен быть изменен.

Если вы не можете сделать это, вы можете упростить запрос, используя IN в предложении where.

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   

Это так близко к вашему желаемому синтаксису, как вы собираетесь получить

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