窗口函数用于计算不同的记录

woo*_*gie 8 sql t-sql sql-server-2008

下面的查询是基于一个复杂的视图,视图按我的意愿工作(我不会包含视图,因为我认为它不会对手头的问题有所帮助).我无法做到的是drugCountsinFamilies专栏.我需要它来向我展示distinct drugName每个药物家族的数量.您可以从第一个screencap看到有三个不同的H3A行.在drugCountsInFamilies为H3A应该是3(有三种不同的H3A药物.)

在此输入图像描述

您可以从第二个屏幕截图中看到,第一个屏幕截图中发生的情况drugCountsInFamilies是捕获列出药物名称的行数.
在此输入图像描述

以下是我的问题,对该部分的评论不正确

select distinct
     rx.patid
    ,d2.fillDate
    ,d2.scriptEndDate
    ,rx.drugName
    ,rx.drugClass
    --the line directly below is the one that I can't figure out why it's wrong
    ,COUNT(rx.drugClass) over(partition by rx.patid,rx.drugclass,rx.drugname) as drugCountsInFamilies
from 
(
select 
    ROW_NUMBER() over(partition by d.patid order by d.patid,d.uniquedrugsintimeframe desc) as rn
    ,d.patid
    ,d.fillDate
    ,d.scriptEndDate
    ,d.uniqueDrugsInTimeFrame
    from DrugsPerTimeFrame as d
)d2
inner join rx on rx.patid = d2.patid
inner join DrugTable as dt on dt.drugClass=rx.drugClass
where d2.rn=1 and rx.fillDate between d2.fillDate and d2.scriptEndDate
and dt.drugClass in ('h3a','h6h','h4b','h2f','h2s','j7c','h2e')
order by rx.patid
Run Code Online (Sandbox Code Playgroud)

如果我尝试在count(rx.drugClass)子句中添加一个distinct,SSMS会生气.可以使用窗口函数完成吗?

Joe*_*tch 19

我遇到了这个问题,寻找解决我计算不同值的问题的方法.在寻找答案时,我发现了这篇文章.见最后评论.我测试了它并使用了SQL.它对我来说真的很好,我想我会在这里提供另一个解决方案.

总之,使用DENSE_RANK(),与PARTITION BY分组列,ORDER BYASCDESC在列数:

DENSE_RANK() OVER (PARTITION BY drugClass ORDER BY drugName ASC) +
DENSE_RANK() OVER (PARTITION BY drugClass ORDER BY drugName DESC) - 1 AS drugCountsInFamilies
Run Code Online (Sandbox Code Playgroud)

我用这个作为自己的模板.

DENSE_RANK() OVER (PARTITION BY PartitionByFields ORDER BY OrderByFields ASC ) +
DENSE_RANK() OVER (PARTITION BY PartitionByFields ORDER BY OrderByFields DESC) - 1 AS DistinctCount
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助!

  • @wootscootinboogie,您应该能够将其标记为可接受的正确答案。比最初标记的容易得多。 (2认同)

Gor*_*off 18

做一个count(distinct)Windows功能需要一个技巧.实际上有几个级别的技巧.

因为您的请求实际上非常简单 - 值始终为1,因为rx.drugClass位于分区子句中 - 我将做出假设.假设您想要计算每个独特药物类别的数量.

如果是这样,请使用row_number()patid和drugClass 进行分区.当这是1,在一个patid,然后一个新的drugClass开始.创建一个在这种情况下为1的标志,在所有其他情况下为0.

然后,您只需sum使用partitioning子句来获取不同值的数量即可.

查询(格式化之后我可以阅读它),如下所示:

select rx.patid, d2.fillDate, d2.scriptEndDate, rx.drugName, rx.drugClass,
       SUM(IsFirstRowInGroup) over (partition by rx.patid) as NumDrugCount
from (select distinct rx.patid, d2.fillDate, d2.scriptEndDate, rx.drugName, rx.drugClass,
             (case when 1 = ROW_NUMBER() over (partition by rx.drugClass, rx.patid order by (select NULL))
                   then 1 else 0
              end) as IsFirstRowInGroup
      from (select ROW_NUMBER() over(partition by d.patid order by d.patid,d.uniquedrugsintimeframe desc) as rn, 
                   d.patid, d.fillDate, d.scriptEndDate, d.uniqueDrugsInTimeFrame
            from DrugsPerTimeFrame as d
           ) d2 inner join
           rx
           on rx.patid = d2.patid inner join
           DrugTable dt
           on dt.drugClass = rx.drugClass
      where d2.rn=1 and rx.fillDate between d2.fillDate and d2.scriptEndDate and
            dt.drugClass in ('h3a','h6h','h4b','h2f','h2s','j7c','h2e')
     ) t
order by patid
Run Code Online (Sandbox Code Playgroud)

  • @GordonLinoff"1 = ROW_NUMBER()...`的情况下,在下一个内联视图中进行后续求和是一个非常棒的大师之举. (2认同)
  • @DougPorter...请不要帮我重新格式化我的代码.您可以在"使用SQL和Excel进行数据分析"的第1章中阅读有关缩进样式的信息.这是非常有意的. (2认同)