使用t-sql为多个子值解析XML

时间:2015-07-30 15:10:53

标签: sql xml tsql

我发送的XML文档无法控制结构。我试图尽可能地规范化数据,并且当我有一个为孩子设置多个值的节点时,我遇到了问题。

理想情况下,我会拆分" ARM_Groups"和" Other_Name"进入单独的表并引用主要干预,但没有" id"要使用的字段。我需要能够分离数据,但要保持这种关系。我有另一个节点,节点内的节点可以重复,并且更复杂,但我想如果我能够掌握这部分的基本把握,我可以想出来。

以下是我正在使用的数据示例:

  <intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Anti-hyperglycemic Agents</intervention_name>
    <description>Multiple drugs including</description>
    <arm_group_label>Glycemia Trial: intensive control</arm_group_label>
    <arm_group_label>Glycemia Trial: standard control</arm_group_label>
    <other_name>glimepiride (Amaryl)</other_name>
    <other_name>metformin (Glucophage)</other_name>
    <other_name>repaglinide (Gluconorm, Prandin)</other_name>
    <other_name>rosiglitazone (Avandia)</other_name>
    <other_name>pioglitazone (Actos)</other_name>
    <other_name>human regular insulin (Novolin ge Toronto)</other_name>
    <other_name>human NPH (Novolin N)</other_name>
    <other_name>human mixed (Novolin 70/30)</other_name>
    <other_name>human isophane (Novolin ge NPH)</other_name>
    <other_name>human 30/70 (Novolin ge 30/70)</other_name>
    <other_name>insulin aspart (NovoRapid, NovoLog)</other_name>
    <other_name>insulin detemir (Levemir)</other_name>
    <other_name>human regular insulin (Novolin R)</other_name>
    <other_name>insulin glargine (Lantus)</other_name>
    <other_name>Acarbose</other_name>
  </intervention>
  <intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Anti-hypertensive Agents</intervention_name>
    <description>Multiple anti-hypertensive agents</description>
    <arm_group_label>BP Trial: intensive control</arm_group_label>
    <arm_group_label>BP Trial: standard control</arm_group_label>
    <other_name>benazepril (Lotensin, Zestril, Altace)</other_name>
    <other_name>chlorthalidone (Thalitone)</other_name>
    <other_name>metoprolol (Toprol XL)</other_name>
    <other_name>diltiazem (Tiazac)</other_name>
    <other_name>plendil (Felodipine)</other_name>
    <other_name>terazosin (Hytrin)</other_name>
    <other_name>candesartan (Atacand)</other_name>
    <other_name>valsartan (Diovan)</other_name>
    <other_name>furosemide</other_name>
    <other_name>reserpine</other_name>
    <other_name>hydralazine</other_name>
    <other_name>carvedilol (Coreg)</other_name>
    <other_name>triamterene / hydrochlorothiazide (Dyazide)</other_name>
    <other_name>metoprolol / hydrochlorothiazide(Lopressor HCT)</other_name>
    <other_name>benazepril / hydrochlorothiazide (Lotensin HCT)</other_name>
    <other_name>lisinopril / hydrochlorothiazide (Zestoretic)</other_name>
    <other_name>candesartan / hydrochlorothiazide (Atacand HCT)</other_name>
    <other_name>valsartan / hydrochlorothiazide (Diovan HCT)</other_name>
    <other_name>amlodipine / benazepril (Lotrel)</other_name>
  </intervention>
  <intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Blinded fenofibrate or placebo plus simvastatin</intervention_name>
    <description>Double blind administration</description>
    <arm_group_label>Lipid Trial: fenofibrate</arm_group_label>
    <arm_group_label>Lipid Trial: placebo</arm_group_label>
    <other_name>fenofibrate (Tricor)</other_name>
  </intervention>

2 个答案:

答案 0 :(得分:2)

据我了解,您需要识别用于创建外键的节点。你可以这样做:

declare @xml xml = N'
<intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Anti-hyperglycemic Agents</intervention_name>
    <description>Multiple drugs including</description>
    <arm_group_label>Glycemia Trial: intensive control</arm_group_label>
    <arm_group_label>Glycemia Trial: standard control</arm_group_label>
    <other_name>glimepiride (Amaryl)</other_name>
    <other_name>metformin (Glucophage)</other_name>
    <other_name>repaglinide (Gluconorm, Prandin)</other_name>
    <other_name>rosiglitazone (Avandia)</other_name>
    <other_name>pioglitazone (Actos)</other_name>
    <other_name>human regular insulin (Novolin ge Toronto)</other_name>
    <other_name>human NPH (Novolin N)</other_name>
    <other_name>human mixed (Novolin 70/30)</other_name>
    <other_name>human isophane (Novolin ge NPH)</other_name>
    <other_name>human 30/70 (Novolin ge 30/70)</other_name>
    <other_name>insulin aspart (NovoRapid, NovoLog)</other_name>
    <other_name>insulin detemir (Levemir)</other_name>
    <other_name>human regular insulin (Novolin R)</other_name>
    <other_name>insulin glargine (Lantus)</other_name>
    <other_name>Acarbose</other_name>
  </intervention>
  <intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Anti-hypertensive Agents</intervention_name>
    <description>Multiple anti-hypertensive agents</description>
    <arm_group_label>BP Trial: intensive control</arm_group_label>
    <arm_group_label>BP Trial: standard control</arm_group_label>
    <other_name>benazepril (Lotensin, Zestril, Altace)</other_name>
    <other_name>chlorthalidone (Thalitone)</other_name>
    <other_name>metoprolol (Toprol XL)</other_name>
    <other_name>diltiazem (Tiazac)</other_name>
    <other_name>plendil (Felodipine)</other_name>
    <other_name>terazosin (Hytrin)</other_name>
    <other_name>candesartan (Atacand)</other_name>
    <other_name>valsartan (Diovan)</other_name>
    <other_name>furosemide</other_name>
    <other_name>reserpine</other_name>
    <other_name>hydralazine</other_name>
    <other_name>carvedilol (Coreg)</other_name>
    <other_name>triamterene / hydrochlorothiazide (Dyazide)</other_name>
    <other_name>metoprolol / hydrochlorothiazide(Lopressor HCT)</other_name>
    <other_name>benazepril / hydrochlorothiazide (Lotensin HCT)</other_name>
    <other_name>lisinopril / hydrochlorothiazide (Zestoretic)</other_name>
    <other_name>candesartan / hydrochlorothiazide (Atacand HCT)</other_name>
    <other_name>valsartan / hydrochlorothiazide (Diovan HCT)</other_name>
    <other_name>amlodipine / benazepril (Lotrel)</other_name>
  </intervention>
  <intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Blinded fenofibrate or placebo plus simvastatin</intervention_name>
    <description>Double blind administration</description>
    <arm_group_label>Lipid Trial: fenofibrate</arm_group_label>
    <arm_group_label>Lipid Trial: placebo</arm_group_label>
    <other_name>fenofibrate (Tricor)</other_name>
  </intervention>'
SELECT 
    t.value('.','nvarchar(max)'),
    t.value('for $a in .. return 1+count($a/../*[. << $a])', 'int') AS intervention_id
FROM 
    @xml.nodes('/intervention/arm_group_label') as t(t)

您将获得每个干预的唯一ID,然后,您可以查询arm_group_label和other_name并使用相同的intervention_id加入它们。

答案 1 :(得分:0)

如果它们具有相同的父级,并且您希望在此示例中按相应的值(即intervention_type)对它们进行分组,则可以创建临时表并单独选择它们:

  declare @doc xml
  set @doc = '<intervention>
    <intervention_type>Drug</intervention_type>
    <intervention_name>Anti-hyperglycemic Agents</intervention_name>
    <description>Multiple drugs including</description>
    <arm_group_label>Glycemia Trial: intensive control</arm_group_label>
    <arm_group_label>Glycemia Trial: standard control</arm_group_label>
    <other_name>glimepiride (Amaryl)</other_name>
    <other_name>metformin (Glucophage)</other_name>
    <other_name>repaglinide (Gluconorm, Prandin)</other_name>
    <other_name>rosiglitazone (Avandia)</other_name>
    <other_name>pioglitazone (Actos)</other_name>
    <other_name>human regular insulin (Novolin ge Toronto)</other_name>
    <other_name>human NPH (Novolin N)</other_name>
    <other_name>human mixed (Novolin 70/30)</other_name>
    <other_name>human isophane (Novolin ge NPH)</other_name>
    <other_name>human 30/70 (Novolin ge 30/70)</other_name>
    <other_name>insulin aspart (NovoRapid, NovoLog)</other_name>
    <other_name>insulin detemir (Levemir)</other_name>
    <other_name>human regular insulin (Novolin R)</other_name>
    <other_name>insulin glargine (Lantus)</other_name>
    <other_name>Acarbose</other_name>
  </intervention>
'


select DENSE_RANK () OVER (ORDER BY b.value('.','varchar(max)')) AS ID
,b.value('(intervention_type)[1]','varchar(max)') as intervention_type
,x.value('.','varchar(max)') as arm_group_label
, y.value('.','varchar(max)') as other_name
into #temp
from @doc.nodes('/intervention') as A(b)
cross apply b.nodes('/intervention/arm_group_label') as N(x)
cross apply b.nodes('/intervention/other_name') as M(y)

    select ID,arm_group_name INTO table1 from #temp

select ID,other_name INTO table2 from #temp