【问题标题】:Date ranges using recursion使用递归的日期范围
【发布时间】:2013-01-04 18:12:32
【问题描述】:

我有一个查询返回的结果类似于下面的创建表查询

create table #testresults
(
  pat_id int,
  fill_date date,
  script_end_date date,
  drug_class char(3),
  distinctDrugs int
)

pat_id 可以提供七种不同类别的药物。 distinctDrugs 列是在fill_datescript_end_date 的时间范围内可以提供pat_id 的不同药物的数量。运行查询的结果如下所示:

每个pat_id 都有许多不同的fill_datescript_end_date 时间段。这些不同的时间段每行有不同的drug_classdistinctDrugs。这个例子的右边两列表示我需要什么:我需要每一行,每个fill_datescript_end_datedrug_classdistinctDrugs 对应每个drug_class。我使用此查询将最右边的两列添加到我的基本视图中

select distinct
 t.pat_id
,t.fill_date
,t.script_end_date
,t.drug_class
,t.distinctDrugs
,h3a.drug_class as h3aDrugClass
,h3a.distinctDrugs
from #temp as t
left join 
(
    select 
     pat_id
    ,fill_date
    ,script_end_date
    ,drug_class
    ,distinctDrugs
    from #temp 
    where drug_class='h3a'
) as h3a on h3a.pat_id=t.pat_id and h3a.fill_date between t.fill_date and t.script_end_date and t.drug_class !=h3a.drug_class
where h3a.drug_class is not null

drug_class 的其余列执行此操作很容易,但这不是很有效。有没有办法更简单地使用递归(或任何其他方式)?

编辑: 这是我正在寻找的最终产品:

select distinct 
 f.pat_id
,f.fill_date
,f.script_end_date
,case when h3a.drug_class is null then 'H3A' else 'H3A' end as H3A
,isnull(h3a.distinctDrugs,0) as h3aCounts
,case when h4b.drug_class is null then 'H4B' else 'H4B' end as H4B
,isnull(h4b.distinctDrugs,0) as h4bCounts
,case when h6h.drug_class is null then 'H6H' else 'H6H' end  as H6H
,isnull(h6h.distinctDrugs,0) as h6hCounts
,case when h2s.drug_class is null then 'H2S' else 'H2S' end as H2S 
,isnull(h2s.distinctDrugs,0) as h2sCounts
,case when h2e.drug_class is null then 'H2E' else 'H2E' end  as H2E
,isnull(h2e.distinctDrugs,0) as h2eCounts
,case when h2f.drug_class is null then 'H2F' else 'H2F' end as H2F
,isnull(h2f.distinctDrugs,0) as h2fCounts
,case when j7c.drug_class is null then 'J7C' else 'J7C' end  as J7C
,isnull(j7c.distinctDrugs,0) as j7cCounts
from familyStrata as f
left join 
(
    select
     pat_id
    ,drug_class
    ,distinctDrugs
    ,fill_date
    from familyStrata 
    where drug_class='h3a'
) as h3a on h3a.pat_id=f.pat_id and h3a.fill_date between f.fill_date and f.script_end_date
left join 
(
    select
     pat_id
    ,drug_class
    ,fill_date
    ,distinctDrugs
    from familyStrata
    where drug_class='h4b'
) as h4b on h4b.pat_id=f.pat_id and h4b.fill_date between f.fill_date and f.script_end_date
left join 
(
    select
     pat_id
    ,drug_class
    ,fill_date
    ,distinctDrugs
    from familyStrata
    where drug_class='h6h'
) as h6h on h6h.pat_id=f.pat_id and h6h.fill_date between f.fill_date and f.script_end_date
left join 
(
    select
     pat_id
    ,drug_class
    ,fill_date
    ,distinctDrugs
    from familyStrata
    where drug_class='h2f'
) as h2f on h2f.pat_id=f.pat_id and h2f.fill_date between f.fill_date and f.script_end_date
left join 
(
    select
     pat_id
    ,drug_class
    ,fill_date
    ,distinctDrugs
    from familyStrata
    where drug_class='h2s'
) as h2s on h2s.pat_id=f.pat_id and h2s.fill_date between f.fill_date and f.script_end_date
left join 
(
    select
     pat_id
    ,drug_class
    ,fill_date
    ,distinctDrugs
    from familyStrata
    where drug_class='h2e'
) as h2e on h2e.pat_id=f.pat_id and h2e.fill_date between f.fill_date and f.script_end_date
left join 
(
    select
     pat_id
    ,drug_class
    ,fill_date
    ,distinctDrugs
    from familyStrata
    where drug_class='j7c'
) as j7c on j7c.pat_id=f.pat_id and j7c.fill_date between f.fill_date and f.script_end_date

这实际上相当快,但绝不是远程优雅/可扩展的。结果集应如下所示:

您可以查看每个时间段内每种不同药物的 drug_class 和 distinctDrugs 编号。现在,对于这个问题,还有比这更优雅的解决方案吗?

【问题讨论】:

  • 您的 final 结果集应该是什么样子还不是很清楚。您是否希望在时间上与当前行中的药物类别重合的每个药物类别都有一个单独的列?
  • 现在很清楚,您希望每个 pat_id 有一行,并且每行可能有许多药物类别。但是,仍然不清楚您希望如何在最终输出中呈现多个类。一种选择可能是将一列用于类名的 CSV 列表,并且可能将另一列用于相应计数的 CSV 列表。或者,您可以为类及其计数设置单独的列。或者,您可以为所有现有类保留列名,从而仅在其中显示计数(或 NULL)。 (还有一个选择是在您的应用程序中处理未透视的输出!)
  • 我将很快用我用来解决它的查询以及查询产生的结果集更新这个问题,希望找到一个更具扩展性的解决方案

标签: sql sql-server sql-server-2008 tsql recursion


【解决方案1】:

在 SQL Server 中,您使用公用表表达式 (CTE) 进行递归查询。方法如下:

http://msdn.microsoft.com/en-gb/library/ms186243(v=sql.105).aspx

【讨论】:

    【解决方案2】:

    因此,递归并不是执行此操作的最佳方法。我和

    select
     pat_id
    ,fill_date
    ,script_end_date
    ,'h3a' as h3a, coalesce(sum(case when drug_class='h3a' then distinctDrugs end),0) as h3aCounts
    ,'h4b' as h4b, coalesce(sum(case when drug_class='h4b' then distinctDrugs end),0) as h4bCounts
    ,'h6h' as h6h, coalesce(sum(case when drug_class='h6h' then distinctDrugs end),0) as h6hCounts
    ,'h2e' as h2e, coalesce(sum(case when drug_class='h2e' then distinctDrugs end),0) as h2eCounts
    ,'h3a' as h2f, coalesce(sum(case when drug_class='h2f' then distinctDrugs end),0) as h2fCounts
    ,'h3a' as h2s, coalesce(sum(case when drug_class='h2s' then distinctDrugs end),0) as h2sCounts
    ,'h3a' as j7c, coalesce(sum(case when drug_class='j7c' then distinctDrugs end),0) as j7cCounts
    ,row_number() over(order by pat_id) as rn
    from x
    group by pat_id,fill_date,script_end_date
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2015-03-16
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      • 2014-01-07
      相关资源
      最近更新 更多