sql server 2008 - SQL SELECT where tag value LIKE -


i attempting make calendar service, within calendar service, there events, , events can tagged metadata searchable.

i want able search records tags must exists (mandatory tags) and/or tags exist (optional tags).

i have managed create query works, when tag value matches 'exactly'. cannot work out how return results tag value '%value%'.

here current implementation

tables , data

create table events (  id int,  eventtext varchar(500) );  create table eventdates (  id int,  eventid int,  startdate datetime,  enddate datetime,  archived bit );  create table tags (  id int,  description varchar(50) );  create table eventtags (  eventid int,  tagid int,  value varchar(50) );  insert events values (1, 'event name 1'); insert events values (2, 'event name 2');  insert eventdates values (1, 1, '2013-01-01', '2013-01-02', 0); insert eventdates values (2, 1, '2013-01-07', '2013-01-08', 0); insert eventdates values (3, 2, '2013-01-02', '2013-01-03', 0);  insert tags values (1, 'tag name 1'); insert tags values (2, 'tag name 2');  insert eventtags values (1, 1, 'value 1'); insert eventtags values (1, 1, 'value 2'); insert eventtags values (1, 2, 'value 1'); insert eventtags values (1, 2, 'value 2'); insert eventtags values (2, 1, 'value 1'); 

query

declare @mandatorytagxml xml declare @optionaltagxml xml declare @startdate datetime declare @enddate datetime declare @searchtypeid smallint  set @startdate = '2013-01-01' set @enddate = '2013-01-31' set @searchtypeid = 1  -- tags must match of set @mandatorytagxml = '<tags>                           <tag>                             <description>tag name 1</description>                             <value>value 1</value>                           </tag>                         </tags>'  -- tags can match 1 or more of set @optionaltagxml = '<tags>                           <tag>                             <description>tag name 2</description>                             <value>value 2</value>                           </tag>                         </tags>'      declare @mandatoryidtable table ([eventid] bigint, [eventdateid] bigint)     declare @optionalidtable table ([eventid] bigint, [eventdateid] bigint)  if(@mandatorytagxml not null) begin     -- select ids matching mandatory tags.     ;with mandatorytags      (       select tagvalue.value('(./value)[1]', 'nvarchar(100)') value,              tagvalue.value('(./description)[1]', 'nvarchar(100)') [description]              @mandatorytagxml.nodes('/tags/tag') t(tagvalue)       )      insert @mandatoryidtable     -- records tags match     select e.id [eventid], ed.id [eventdateid]     [dbo].[events] e     inner join [dbo].[eventdates] ed on ed.eventid = e.id     ed.startdate >= @startdate     , ed.enddate <= @enddate     , ed.archived = 0     , not exists (                     select t.id, c.value                     mandatorytags c join tags t                         on c.[description] = t.[description]                     except                     select t.tagid, t.value                     [eventtags] t                     t.eventid = e.id                                               ) end else -- select records  begin     insert @mandatoryidtable     -- records tags match     select e.id [eventid], ed.id [eventdateid]     [dbo].[events] e     inner join [dbo].[eventdates] ed on ed.eventid = e.id     ed.startdate >= @startdate     , ed.enddate <= @enddate     , ed.archived = 0 end      ;with optionaltags      (       select tagvalue.value('(./value)[1]', 'nvarchar(100)') value,              tagvalue.value('(./description)[1]', 'nvarchar(100)') [description]              @optionaltagxml.nodes('/tags/tag') t(tagvalue)       )      insert @optionalidtable     -- records tags match     select e.id [eventid], ed.id [eventdateid]     [dbo].[events] e     inner join [dbo].[eventdates] ed on ed.eventid = e.id     ed.startdate >= @startdate     , ed.enddate <= @enddate     , ed.archived = 0     , exists (                 select t.id, c.value                 optionaltags c join tags t                     on c.[description] = t.[description]                 intersect                 select t.tagid, t.value                 [eventtags] t                 t.eventid = e.id                                           )  -- determine if need factor in optional tags in result set if (@optionaltagxml not null) begin     -- select results exist in both optional , mandatory tables     select distinct m.*     @mandatoryidtable m     inner join @optionalidtable o on o.eventid = m.eventid , o.eventdateid = m.eventdateid end else begin     -- select results exist in mandatory table     select distinct m.*     @mandatoryidtable m end 

i have created sqlfiddle demo it.

my idea use @searchtypeid switch between exact match searching , match searching.

(note not dba, there may better ways this. open suggestions)

can offer suggestions how matches on tag values?

many thanks

i think idea of using type of flag/switch change matching type work. implemented using words instead of ids, if toggle join condition based on search type, should matching expected.

fiddle: http://sqlfiddle.com/#!3/d9fbd/3/0

i first added tag similar tag 1 , attached event 2 testing.

insert tags values (3, 'different tag name 1'); insert eventtags values (2, 3, 'value 3'); 

i created search type flag/switch.

declare @searchtype nvarchar(10) set @searchtype = 'like' --other type exact 

so can toggle exists join condition based on flag. changed not exists exists understanding. below new join condition, using mandatory tag block example.

    -- select ids matching mandatory tags. ;with mandatorytags  (   select tagvalue.value('(./value)[1]', 'nvarchar(100)') value,          tagvalue.value('(./description)[1]', 'nvarchar(100)') [description]          @mandatorytagxml.nodes('/tags/tag') t(tagvalue)   )  insert @mandatoryidtable -- records tags match or select e.id [eventid], ed.id [eventdateid] [dbo].[events] e inner join [dbo].[eventdates] ed on ed.eventid = e.id ed.startdate >= @startdate , ed.enddate <= @enddate , ed.archived = 0 , exists (                 -- care tag ids here, not values                 select t.id                 mandatorytags c join tags t                     on (                       -- toggle join type based on flag/switch                       (@searchtype = 'exact' , c.[description] = t.[description])                       or                       (@searchtype = 'like' , t.[description] ('%' + c.[description] + '%'))                     )                 intersect                 select t.tagid                 [eventtags] t                 t.eventid = e.id                                           ) 

i'm sure there re-factoring , optimization can in sql, should @ least give 1 idea on how matching if desired. hope helps!


Comments

Popular posts from this blog

c# - Send Image in Json : 400 Bad request -

jquery - Fancybox - apply a function to several elements -

An easy way to program an Android keyboard layout app -