Sql server 在SQL Server中检索分层父/子数据

Sql server 在SQL Server中检索分层父/子数据,sql-server,query-performance,hierarchical-data,Sql Server,Query Performance,Hierarchical Data,在我的应用程序中,有一个治疗区域字段,在选择它之后,用户可以选择疾病,然后选择其他4个亚型。所有这6个字段都是多选字段,其中只有4个亚型字段是可选的,治疗区域和疾病是强制性的。这意味着用户可以/不可以选择子类型。如果他选择,它可以是任何级别,而不是强制要求它必须是所有的4。 疾病表的结构如下所示 ID Name DiseaseIdParent TherapeuticID DiseaseCode SubDisease1 SubDisease2 SubDisease3 1

在我的应用程序中,有一个治疗区域字段,在选择它之后,用户可以选择疾病,然后选择其他4个亚型。所有这6个字段都是多选字段,其中只有4个亚型字段是可选的,治疗区域和疾病是强制性的。这意味着用户可以/不可以选择子类型。如果他选择,它可以是任何级别,而不是强制要求它必须是所有的4。 疾病表的结构如下所示

ID  Name          DiseaseIdParent TherapeuticID DiseaseCode SubDisease1  SubDisease2  SubDisease3

1   DiseaseMain    NULL              1            M40          NULL         NULL         NULL
2   DiseaseSub1    1                 1            M40          NULL         NULL         NULL
3   DiseaseSub2    1                 1            M41           2           NULL         NULL
4   DiseaseSub3    1                 1            M42           2            3           NULL
5   DiseaseSub4    1                 1            M41           2            3            4
下面是我使用递归CTE所做的尝试

;WITH DiseaseCTE AS 
       (
            SELECT
            hv.ID as hvId,th.Id as ThId,th.Name as ThName,ds.Id diseaseId,ds.Name as diseaseName
            ,CAST('0' as int) as diseaseId1,CAST('0' as varchar(1000)) as diseaseName1,CAST('0' as int) as diseaseId2
            ,CAST('0' as varchar(1000)) as diseaseName2
            ,CAST('0' as int) as diseaseId3,CAST('0' as varchar(1000)) as diseaseName3,CAST('0' as int) as diseaseId4,CAST('0' as varchar(1000)) as dsName4,ds.ICD_Code,CAST('0' as varchar(20)) as diseaseCode1,CAST('0' as varchar(20)) as diseaseCode2
            ,CAST('0' as varchar(20)) as diseaseCode3,CAST('0' as varchar(20)) as diseaseCode4

            FROM RecordTbl hv
            INNER JOIN RecordTherapeuticTbl ta on hv.Id=ta.RecordId
            INNER JOIN TherapeuticTbl th on th.ID=ta.TherapeuticId
            INNER JOIN DiseaseTbl ds on ds.TherapeuticIdID=th.ID
            INNER JOIN RecordPrimaryDisease pdhv on pdhv.RecordId=hv.ID and pdhv.Disease_Id=ds.Id and pdhv.RecordId in(2231,2232)

            WHERE hv.Id in(2231,2232)
            GROUP BY 
            hv.ID,th.Id,th.Name,ds.Id,ds.Name
            ,ds.DiseaseCode
              
            UNION ALL

            SELECT
            th.HvId as hvId ,th.ThId as ThId,th.ThName,th.diseaseId,th.dsName as diseaseName
            ,dss1.ID as diseaseId1,dss1.Name as diseaseName1,dss2.ID as diseaseId2,dss2.Name as diseaseName2
            ,dss3.ID as diseaseId3,dss3.Name as diseaseName3
            ,dss4.ID as diseaseId4,dss4.Name as diseaseName4
            ,th.ICD_Code as diseaseCode,dss1.DiseaseCode as diseaseCode1,dss2.DiseaseCode as diseaseCode2
            ,dss3.DiseaseCode as   diseaseCode3
            ,dss4.DiseaseCode as diseaseCode4
            FROM DiseaseCTE th 
            INNER JOIN DiseaseTbl dss1 on dss1.TherapeuticId=th.ThId and dss1.DiseaseIdParent=th.diseaseId
            INNER JOIN DiseaseTbl dss2 on dss2.TherapeuticId=th.ThId and dss2.SubDisease1=dss1.ID
            INNER JOIN DiseaseTbl dss3 on dss3.TherapeuticId=th.ThId and dss3.SubDisease2=dss2.ID
            INNER JOIN DiseaseTbl dss4 on dss4.TherapeuticId=th.ThId and dss4.SubDisease3=dss3.ID
            INNER JOIN RecordDiseaseSubtype sb1 on  sb1.DiseaseID=dss1.ID and sb1.RecordId  in(2231,2232)
            INNER JOIN RecordDiseaseSubtype2 sb2 on sb2.DiseaseID=dss2.ID and sb2.RecordId  in(2231,2232)
            INNER JOIN RecordDiseaseSubtype3 sb3 on sb3.DiseaseID=dss3.ID and sb3.RecordId  in(2231,2232)
            INNER JOIN RecordDiseaseSubtype4 sb4 on sb4.DiseaseID=dss4.ID and sb4.RecordId in(2231,2232)
            WHERE th.hvId in(2231,2232)
              
       )  


              select * from DiseaseCTE
                        GROUP BY 
              hvId,ThId,ThName,diseaseId,diseaseName
            ,diseaseId1, diseaseName1,diseaseId2, diseaseName2
            ,diseaseId3, diseaseName3
            ,diseaseId4,diseaseName4
            ,diseaseCode,diseaseCode1,diseaseCode2
            ,diseaseCode3
            ,diseaseCode4
预期产量



+----------+---------------+-----------------+-------------------------+-------------------+-------------------------------+----------------------------------+-------------------------------------------+-------------+-----------------+-----------------+-----------------+-----------------+
| RecordId | TheraupeticId | TheraupeticName |       diseaseName       |    SubDisease1    |          SubDisease2          |           SubDisease3            |                SubDisease4                | DiseaseCode | SubDiseaseCode1 | SubDiseaseCode2 | SubDiseaseCode3 | SubDiseaseCode4 |
+----------+---------------+-----------------+-------------------------+-------------------+-------------------------------+----------------------------------+-------------------------------------------+-------------+-----------------+-----------------+-----------------+-----------------+
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, acute myocardial infarction | ACS, acute myocardial infarction, type 2  | I24.9       | I24.9           | I24.9           | I21             | I21.9           |
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, acute myocardial infarction | ACS, acute myocardial infarction, type 4b | I24.9       | I24.9           | I24.9           | I21             | I21.9           |
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, acute myocardial infarction | ACS, acute myocardial infarction, type 5  | I24.9       | I24.9           | I24.9           | I21             | I21.9           |
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, myocardial infarction       | ACS, myocardial infarction, type 2        | I24.9       | I24.9           | I24.9           | I21             | I21             |
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, myocardial infarction       | ACS, myocardial infarction, type 4b       | I24.9       | I24.9           | I24.9           | I21             | I21             |
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, angina                      | ACS, stable angina                        | I24.9       | I24.9           | I24.9           | I20             | I20             |
|     2231 |            56 | Cardiovascular  | Coronary heart diseases | Coronary syndrome | Acute coronary syndrome (ACS) | ACS, angina                      | ACS, unstable angina                      | I24.9       | I24.9           | I24.9           | I20             | I20.9           |
|     2231 |            58 | Other           | Symptoms                | Dyspnea           | Respiratory dyspnea           | Respiratory distress/disease     | Acute respiratory distress/disease        | R10.2       | R06.0           | J80             | J80             | J80             |
+----------+---------------+-----------------+-------------------------+-------------------+-------------------------------+----------------------------------+-------------------------------------------+-------------+-----------------+-----------------+-----------------+-----------------+




You can see, there are 2 Theraupetics for this particular record 2231, SubDisease4 is the last branch. I want to fetch top 5 based on DiseaseCodes, here we will consider SubDiseaseCode4 because it is the last branch, and in this example the last branch is SubDisease4, for other records it might be Subdisease2 or SubDisease3 or might be none. Top 5 sets will be like for 
Eg: Set 1 would be till type 2
    Set 2 would be till type 4b
    .....Continues

你可以看到它打开的树枝。如何为多个记录构造数据,假设某个数据以DiseaseSubite2结尾,作为最后一个分支,因为内部连接按照我尝试的逻辑失败。此外,如前所述,由于我们无法通过in运算符下的25K,因此可以对大量记录执行哪些操作

名称中前缀为“Record”的表是事务表,为相应的记录Id选择了疾病。我面临的问题是:

  • 如前所述,子章节并非虚构的,根据记录可能会有所不同。有些可能在4岁或2岁之前没有。左连接对RecirsiveCenter不起作用。在递归部分
  • 抛下错误 语句终止。在语句完成之前,已用尽最大递归100。 如果我修复它,我将获得层次结构,但正如您所知,即使是RecordID也是至关重要的。因为它为父部分和递归部分返回相同的ID,例如:2231,所以出现了这个问题

  • in操作符中有许多记录,因为这是动态的,这将增加到25K(仍在增加),正如我所提到的,并非所有记录的子类型都是统一的,它可能会根据这些记录的不同而变化,这会影响性能,有些记录的连接也会失败,因为子类型表可能不包含RecordID。例如:2231可能仍然有子类型1,2232将有子类型3,并且内部连接在那里失败
  • 这是许多多种选择,取决于多种治疗疾病,选择的分支只会扩大,我必须根据每个记录的疾病代码获得其中的最佳5个组合

    动态查询是我能记住的一件事,但是运行数千条记录的循环可能会带来性能问题

    我在这里是为了一个及时的建议,如果提供一个将是有益的


    谢谢..

    有一个选项可以否决100次迭代的默认maxrecursion,但是一些数据库重新设计可能更合适。表结构,如
    RecordDiseaseSubiteType
    RecordDiseaseSubite2
    RecordDiseaseSubite3
    RecordDiseaseSubite4
    Disease.SubDisease1
    Disease.SubDisease2
    ,都是重新设计的标志。将25K值传递给操作符中的
    ,看起来也不理想。这应该是一个25K行的表连接。感谢@Sander的响应。但不幸的是,这些都存在于生产中,重新设计可能需要一些时间。在这一切中你有什么办法吗?所以我可以在上面做得更好。忽略数据库设计,这个查询的目的是什么?您可以解释查询不起作用的原因,但不能解释您希望从中得到什么(即所有疾病和选定子疾病的概述?)。除了
    疾病
    表和预期输出之外,请提供一些样本数据。桑德,我已经按照您的坚持对样本数据进行了编辑,如果您还有什么需要我提及的,请告诉我。
    th.HvId as hvId
    
    in(2231,2232)