SQL Server:如何使用分隔符过滤多对多关系

时间:2014-08-15 02:54:05

标签: sql-server

我有一个Disease和一个Symptoms表,其中包含Disease_Symptoms的桥接表

例如,我有这些条目

Disease1  
    (symptoms1, symptoms2, symptoms6, symptoms7)

Disease2  
    (symptoms1, symptoms3, symptoms8)

Disease3  
    (symptoms1, symptoms4)

Disease4
    (symptoms2, symptoms8)

然后我使用symptoms1过滤搜索:

输出:

disease1, disease2, disease3

然后我想添加symptoms8

的过滤搜索

OUTPUT应该是:仅disease2 disease4被忽略,因为它没有symptoms1

我如何在查询中执行此操作?我创建了一个存储过程,但它只能搜索单个症状而不再搜索。

我问了一位同事有关这个问题,他告诉我我需要使用逗号分隔符,但我不知道怎么做。我无法理解其他网站中的一些例子。

你能以一种基本可以理解的方式向我展示一点这种方法吗?

这是我的存储过程:

CREATE PROCEDURE SP_RetrieveDiseaseSymptoms
    @Id int = 0
    ,@DiseaseId int = 0
    ,@SymptomId int = 0
    ,@Toggle bit = 0
    ,@UserId int = 0
    ,@SearchText AS NVARCHAR(100) = ''
    ,@SearchCriteria AS NVARCHAR(100) = ''
AS
BEGIN
    SET NOCOUNT ON;

    SELECT 
      ISNULL(DS.Id,0) as Id
      ,ISNULL(DS.DiseaseId, 0) as DiseaseId
      ,ISNULL(D.DiseaseName, '') as DiseaseName
      ,ISNULL(D.Description, '') as Description
      ,ISNULL(DS.SymptomId, 0) as SymptomId
      ,ISNULL(S.Name, '') as SymptomName
      ,ISNULL(DS.StatusId, 0) as StatusId
      ,ISNULL(DS.CreatedBy, 1) as CreatedById
      ,CB.FirstName + ', ' + CB.LastName as CreatedByName
      ,ISNULL(DS.CreatedOn, '1/1/1753') as CreatedOn
      ,ISNULL(DS.ModifiedBy, 1) as ModifiedById
      ,CM.LastName + ', ' + CM.FirstName as CreatedByName
      ,ISNULL(DS.ModifiedOn , '1/1/1753')as ModifiedOn     
    FROM 
       Disease_Symptoms DS  

    LEFT JOIN 
       Users CB ON CB.Id = DS.CreatedBy
    LEFT JOIN 
       Users CM ON CM.Id = DS.ModifiedBy
    LEFT JOIN 
       Diseases D ON D.Id = DS.DiseaseId
    LEFT JOIN 
       Symptoms S ON S.Id = DS.SymptomId

    WHERE 
       (DS.Id = @Id OR @Id = 0) 
       AND (D.Id = @DiseaseId OR @DiseaseId = 0)
       AND (S.Id = @SymptomId OR @SymptomId = 0)      
       AND DS.StatusId <> 0 

END
GO

示例数据

==============

Diseases table

D_Id  D_name

1     AIDS

2     Bird Flu

3     Mad Cow

4     Osteoporosis

==============

Symptoms table

S_Id   S_name

1      Drooling

2      Blurred retina

3      Cough

4      Fever

5      Yellowish gums

6      Dark blue tongue

7      Falling furs

8      Poor appetite

==============

Disease_Symptoms table

DS_Id   D_Id   S_Id

1        1      1 (AIDS - Drooling)

2        1      2 (AIDS - Blurred retina)

3        1      6 (AIDS - Dark blue tongue)

4        1      7 (AIDS - Falling furs)

5        2      1 (Bird flu - Drooling)

6        2      3 (Bird flu - Cough)

7        2      8 (Bird flu - Poor appetite)

8        3      1 (Mad cow - Drooling)

9        3      4 (Mad cow - Fever)

10       4      2 (Osteoporosis - Blurred retina)

11       4      8 (Osteoporosis - Poor appetite)

然后我会搜索任何有以下症状的疾病:流口水(symptom_id = 1)

输出:

AIDS
Bird flu
Mad cow

然后,我想添加另一个症状,但查询应该只搜索之前的三个输出(艾滋病,禽流感,疯牛病)并忽略最后一种疾病(骨质疏松症),因为它没有症状_id = 1(流口水)。

搜索症状:食欲不振(symptom_id = 8)

输出:

Bird flu

2 个答案:

答案 0 :(得分:1)

这是一种方式:

SELECT D_name
FROM Diseases d
WHERE EXISTS (SELECT * FROM Disease_Symptoms ds1 WHERE ds1.D_id=d.D_id AND ds1.S_id=1)
AND EXISTS (SELECT * FROM Disease_Symptoms ds8 WHERE ds8.D_id=d.D_id AND ds8.S_id=8)

答案 1 :(得分:0)

取决于您希望如何显示答案,取消两次:

您可以获取输入字符串并将其转换为表格(查找fn_split以查看方式),然后您可以计算匹配数量,并且只记录teh计数与临时表中的总记录匹配的记录。

create table #temp (id int)

Insert into #temp
values (1), (2), (3)

create table #temp2 (testid int,id int, test varchar (30))

insert into #temp2
values (1,1, 'test') ,(1,5, 'test2'), (2,1,'Test3') ,(2,2,'test4'), (2,3, 'test5')

select  tp2.testid, tp2.id, tp2.test from #temp2 tp2
join (select testid from #temp2 t2
join #temp t on t.id = t2.id
group by testid
having count(*) = (select count(*) from #temp)) mycount
on tp2.testid = mycount.testid

或者您可以使用输入字符串变量和FOR XML PATH来显示连接值

declare @Concatstg varchar(100) = '1,2,3'
select *
from
(
        select distinct t2.testid, STUFF((SELECT  ',' + cast(t1.id as varchar (20) )
        FROM #temp2  t1 where t2.testid = t1.testid 
        FOR XML PATH('')), 1, 1, '')  as Concatstr
        from #temp2 t2
     ) Derivedtable     
where        Concatstr = @Concatstg