Лично я использую динамические запросы для таких выборок.
- Код: Выделить всё
ALTER procedure uspSetProject
@ProjectID int
as
declare @Joins varchar(500)
declare @Existances varchar(700)
declare @Likes varchar(1700)
declare @All nvarchar(4000)
set @Joins = dbo.BuildJoins(@ProjectID, 1)
set @Existances = dbo.BuildExistances(@ProjectID)
set @Likes = dbo.BuildLikes(@ProjectID)
if len(@Existances) > 0 and len(@Likes) > 0 set @Existances = @Existances + ' and '
if len(@Existances) <> 0 or len(@Likes) <> 0 begin
set @All = 'insert into datProjectOrgs (ProjectID, OrgID) select distinct ' + cast(@ProjectID as varchar(8)) + ', datOrganisations.OrgID ' + @Joins + @Existances + @Likes
print @all
exec (@All)
end
---------------------------------------------------------------------------
ALTER function BuildLikes(@ProjectID int)
returns varchar(2700)
as
begin
declare @DataField varchar(50), @Table varchar(50)
declare @FieldValue varchar(128)
declare @Likes varchar(2700)
declare @ObjectID int
declare @ct smallint
declare Objects cursor fast_forward for
select distinct ObjectID
from tblProjectRules
inner join tblObjectFields on tblObjectFields.FieldID = tblProjectRules.FieldID
where (tblObjectFields.CompareType = 1 or
tblObjectFields.CompareType = 3) and
ProjectID = @ProjectID
set @Likes = ''
open Objects
fetch next from Objects into @ObjectID
WHILE @@FETCH_STATUS = 0
begin
set @Likes = @Likes + '('
declare Fields cursor for
select distinct
DataField,
[Table],
FieldValue,
CompareType
from tblProjectRules
inner join tblObjectFields on tblObjectFields.FieldID = tblProjectRules.FieldID
where (tblObjectFields.CompareType = 1 or
tblObjectFields.CompareType = 3) and
ProjectID = @ProjectID and
ObjectID = @ObjectID
open Fields
fetch next from Fields into @DataField, @Table, @FieldValue, @ct
WHILE @@FETCH_STATUS = 0
begin
if @ct = 1
set @Likes = @Likes + @Table + '.' + @DataField + ' like ' + char(39) + '%' + @FieldValue + '%' + char(39) + ' or '
if @ct = 3
set @Likes = @Likes + @Table + '.' + @DataField + ' = ' + @FieldValue + ' or '
fetch next from Fields into @DataField, @Table, @FieldValue, @ct
end
close Fields
deallocate Fields
set @Likes = substring(@Likes, 1, len(@Likes) - 3) + ') and '
fetch next from Objects into @ObjectID
end
close Objects
deallocate Objects
if len(@Likes)>0 set @Likes = substring(@Likes, 1, len(@Likes) - 4)
return @Likes
end
---------------------------------------------------------------------------------
ALTER function BuildJoins(@ProjectID int, @SingleID bit)
returns varchar(500)
as
begin
/*
declare @ProjectID int
set @ProjectID =160
*/
declare @Joins varchar(500), @ObjectID int
declare Objects cursor fast_forward for
select distinct ObjectID
from tblProjectRules
inner join tblObjectFields on tblObjectFields.FieldID = tblProjectRules.FieldID
where ProjectID = @ProjectID
if @SingleID = 0
set @Joins = 'from datOrganisations left join cvOrganisationsList on datOrganisations.OrgID = cvOrganisationsList.OrgID ' + char(10)
else
set @Joins = 'from datOrganisations ' + char(10)
open Objects
fetch next from Objects into @ObjectID
WHILE @@FETCH_STATUS = 0
begin
set @Joins = @Joins + case @ObjectID
when 1 then ''
when 2 then 'inner join datOrgActivities on datOrgActivities.OrgID = datOrganisations.OrgID ' + char(10)
when 3 then 'inner join datPhones on datPhones.OrgID = datOrganisations.OrgID ' + char(10)
when 4 then 'inner join datOrgStaff on datOrgStaff.OrgID = datOrganisations.OrgID ' + char(10)
end
fetch next from Objects into @ObjectID
end
close Objects
deallocate Objects
set @Joins = @Joins + 'where '
-- print @Joins
return @Joins
end
--------------------------------------------------------------------------------
ALTER function BuildExistances(@ProjectID int)
returns varchar(700)
as
begin
/*
declare @ProjectID int
set @ProjectID = 162
*/
declare @Prefix varchar (400)
declare @Existances varchar(700)
declare @Table varchar(50), @FieldID int
declare @Field varchar(50)
declare Existance cursor fast_forward for
select distinct tblProjectRules.FieldID,
DataField,
[Table]
from tblProjectRules
inner join tblObjectFields on tblObjectFields.FieldID = tblProjectRules.FieldID
where tblObjectFields.CompareType = 2 and
ProjectID = @ProjectID
set @Existances = ''
set @prefix = 'exists (select FieldValue from tblProjectRules where ProjectID = ' + cast(@ProjectID as varchar(5)) + ' and FieldID = '
open Existance
fetch next from Existance into @FieldID, @Field, @Table
WHILE @@FETCH_STATUS = 0
begin
set @Existances = @Existances +
@prefix + cast(@FieldID as varchar(5)) +
' and FieldValue = ' + @Table + '.' +
@Field + ') and ' + char(10)
fetch next from Existance into @FieldID, @Field, @Table
end
close Existance
deallocate Existance
if len(@Existances) > 0
set @Existances = substring(@Existances, 1, len(@Existances)-5)
/*
print @Existances
print len(@Existances )
*/
return @Existances
end
Способ работает так. Во вспомогательную таблицу tblObjectFields заносятся таблицы и их поля, по которым нужно проводить поиск, а так же указывается тип сравнения: 1 - через like, 2 - через exists в подчиненных таблицах основного объекта (в данной реализации основной объект - огранизация, подчиненные - виды деятельности, телефоны и т.п), 3 - прямое сравнение id основного объекта (тебе не нужно). В таблицу tblProjectRules заносятся значения и идентификаторы полей, по которым производится поиск, и идентификатор поиска. В конце вызывается процедура uspSetProject.
В твоем случае в этой процедуре нужно заменить set @Existances = @Existances + '
and ' на set @Existances = @Existances + '
or ' и вместо insert делать сразу select.
В функции BuildLikes заменить set @Likes = substring(@Likes, 1, len(@Likes) - 3) + ')
and ' на set @Likes = substring(@Likes, 1, len(@Likes) - 3) + ')
or ', в BuildJoins заменить все inner join на left join.
Хотя джойны и exists'ы тебе тоже не понадобятся; судя по условиям, шерстить подчиненные таблицы не надо. Достаточно создать вьюхи, представляющие все документы со всеми полями, по которым нужно проводить поиск. И еще тебе нужно добавить сравнение временных промежутков.
Вообще-то, этот способ более универсален, чем требуется тебе. Он позволяет проводить поиск по поизвольному количеству критериев и их значений. Единственное, что не позволяет, так это выбирать условия поиска. Например, если в качестве критериев указаны пара названий организации и пара видов деятельности, то без указанных выше изменений будет производится поиск типа (название OR название) AND (вид OR вид), а с изменениями - (название OR название) OR (вид OR вид).
Лучший способ понять что-то самому — объяснить это другому.