Запрос из одной таблицы

sqlprof

Всем программистам привет! Respect! Недавно перешел на Transact Sql, что даёт о себе знать. Сразу возникает множество проблем, но сейчас есть одна проблемка просто для меня неподъёмная. Допустим есть некая табличка, состоящая из следующих полей Sn_pol (полис больного), c_i (история болезни больного), mcod (код поликлиники), k_i (количество дней которые проболел больной в больнице), dDate_gospit (дата госпитализации больного), d_i (дата выписки больного). Необходимо сделать следующее: берем к примеру первую строку таблицы (раньше работал на Foxe, поэтому ещё остались такие ассоциации, здесь так неполучится, наверное) и смотрим промежуток времени, который проболел больной (т. е. начало болезни ddate_gospit и конец болезни d_u), затем идет вторая строка и если sn_pol изменился, то идем на другую строку. Если при переходе на новую строку sn_pol неизменился, c_i неизменилось и mcod неизменился , то идем дальше. Если меняется c_i или mcod, то необходимо сопоставить время, котрое проболел больной в первой строке с временем в данной строке и если окажется так, что период времени болезни во второй строке находится внутри периода болезни первой строки( т. е. допустим проболел с 01.01.2006. по 10.01.2006 ,а во второй записи с 04.01.2006 по 06.01.2006), то все записи с этим sn_pol поместить в view, или есть пересечение периодов дат тоже поместить в view. Количество записей для одного и того же sn_pol может быть любым. Как такое реализовать на transact sql незнаю. Подскажите пожалуйста как быть-то или технологию подобного рода задач. Спасибо! Respect!
8 ответов

sqlprof

чуть глаза не сломао, пока прочел....а что имеется в виду под view?по идее, для последовательного перебора строк используются CURSORы. Но, вероятно, можно и без него.Если бы ты объяснял не свой алгоритм перебора записей, а смысл задачи, было бы лучше.


sqlprof

Смысл задачи такой, что есть некая больница, соответственно с больными у которых есть свои истории болезней. Необходимо исключить такие ситуации когда больной проходит лечение в разных больницах в одно и тоже время или когда эти даты пересекаются ведь не может такого быть чтобы было лечение "одного" человека в разных стационарах или лечение в одном под разными историями болезни. Поля в таблице см. выше.


sqlprof

select t1.* from t t1 where exists(select 1 from t where sn_pol=t1.sn_pol and((dDate_gospit between t1.dDate_gospit and t1.d_i) or (d_i between t1.dDate_gospit and t1.d_i) or (dDate_gospit t1.d_i)) and mcod<>t1.mcod)


sqlprof

Вы же сами пишите, что "Необходимо ещё раз отметить, что вышеописанные приёмы можно применять только с множествами, где нет повторяющихся значений". А в моём случае есть повторение. Интересно, как использовать курсор?


sqlprof

uus объясни пожалуйста, что значит select 1. Видел подобное в книгах, но сам никогда не использовал.


sqlprof

exists - это логика, поэтому в select может быть что угодно, просто 1 это самое быстрое что можно набрать, можно и *


sqlprof

вот така страшненькая штука получилась. она призвана вывести все записи с пересекающимися диапозонами у одинаковых sn_pol. ессно, это только демонстрация принципа..
declare @t table (	p_key int identity(<b>1</b>,<b>1</b>),
			Sn_pol 	/*(полис больного)*/ int,
			c_i 	/*(история болезни больного)*/ int,
			mcod 	/*(код поликлиники)*/ int,
			s_date /*(дата госпитализации больного)*/ datetime,
			e_date 	/*(дата выписки больного)*/ datetime
		)

insert into @t (Sn_pol,c_i,mcod,s_date,e_date)	select <b>1</b>,<b>1</b>,<b>1</b>,getdate()-<b>5</b>, getdate()
insert into @t (Sn_pol,c_i,mcod,s_date,e_date)	select <b>1</b>,<b>1</b>,<b>2</b>,getdate()-<b>9</b>, getdate()-<b>2</b>
insert into @t (Sn_pol,c_i,mcod,s_date,e_date)	select <b>2</b>,<b>1</b>,<b>1</b>,getdate()-<b>5</b>, getdate()
insert into @t (Sn_pol,c_i,mcod,s_date,e_date)	select <b>3</b>,<b>1</b>,<b>1</b>,getdate()-<b>5</b>, getdate()
insert into @t (Sn_pol,c_i,mcod,s_date,e_date)	select <b>1</b>,<b>3</b>,<b>1</b>,getdate()-<b>5</b>, getdate()
insert into @t (Sn_pol,c_i,mcod,s_date,e_date)	select <b>2</b>,<b>1</b>,<b>1</b>,getdate()-<b>7</b>, getdate()+<b>5</b>


select t1.p_key, t2.p_key, t3.p_key, t1.sn_pol
from 	@t t1
	left join @t t2 on t2.s_date < t1.e_date
		and t2.e_date >= t1.e_date
		and t1.sn_pol = t2.sn_pol
		and t1.p_key != t2.p_key
	left join @t t3 on t3.s_date < t1.s_date
		and t3.e_date >= t1.s_date
		and t1.sn_pol = t3.sn_pol
		and t1.p_key != t3.p_key
where t2.p_key is not null or t3.p_key is not null