繁体   English   中英

Window 函数对不同的记录进行计数

[英]Window functions to count distinct records

下面的查询基于一个复杂的视图,该视图按我的意愿工作(我不打算包含该视图,因为我认为它不会帮助解决手头的问题)。 我不能正确的是drugCountsinFamilies列。 我需要它来向我显示每个药物系列的distinct drugName的数量。 您可以从第一个屏幕截图中看到有三个不同的 H3A 行。 H3A 的drugCountsInFamilies应该是 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

如果我尝试在count(rx.drugClass)子句中添加 distinct,SSMS 会发疯。 可以使用 window 函数来完成吗?

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

总之,使用DENSE_RANK()PARTITION BY分组列, ORDER BY ASCDESC对列进行计数:

DENSE_RANK() OVER (PARTITION BY drugClass ORDER BY drugName ASC) +
DENSE_RANK() OVER (PARTITION BY drugClass ORDER BY drugName DESC) - 1 AS drugCountsInFamilies

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

DENSE_RANK() OVER (PARTITION BY PartitionByFields ORDER BY OrderByFields ASC ) +
DENSE_RANK() OVER (PARTITION BY PartitionByFields ORDER BY OrderByFields DESC) - 1 AS DistinctCount

我希望这有帮助!

count(distinct)作为Windows函数需要一个技巧。 实际上有几个级别的技巧。

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

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

然后,您可以简单地使用分区子句进行sum以获取不同值的数量。

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

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

我认为您尝试做的是将其作为窗口函数:

COUNT(DISTINCT rx.drugName) over(partition by rx.patid,rx.drugclass) as drugCountsInFamilies

哪个 SQL 抱怨。 但是你可以这样做:

SELECT 
rx.patid
, rx.drugName
, rx.drugClass
, (SELECT COUNT(DISTINCT rx2.drugName) FROM rx rx2 WHERE rx2.drugClass = rx.DrugClass AND rx2.patid = rx.patid) As drugCountsInFamilies
FROM rx
...

如果表很大,那么最好将索引放在其中一列(例如 patid)上,这样嵌套查询就不会消耗大量资源。

select max(dense_rank() over (order by name desc partition by family)) over (partition by family) 

这能行吗?

为什么这样的事情不起作用?

SELECT 
   IDCol_1
  ,IDCol_2
  ,Count(*) Over(Partition By IDCol_1, IDCol_2 order by IDCol_1) as numDistinct
FROM Table_1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM