【问题标题】:SQL Server Count Distinct records with a specific condition in window functionsSQL Server在窗口函数中计算具有特定条件的不同记录
【发布时间】:2021-07-18 02:55:26
【问题描述】:

我有一个类似于下面的表格:

Group TradeMonth flag
A Jan 1
A Mar 1
A Mar 0
A Jun 0
B Feb 1
B Apr 1
B Sep 1
B Sep 1

我需要有一列用于计算 每个组具有非零值 (flag=1) 的不同个月数。我更喜欢使用窗口函数(不是分组依据),并且我知道在 sql server 的窗口函数中不允许使用不同的计数,因此非常感谢任何关于如何使用窗口函数计算它的解决方案。 结果应该如下:

Group TradeMonth flag #of flagged_months(Distinct)
A Jan 1 2
A Mar 1 2
A Mar 0 2
A Jun 0 2
B Feb 1 3
B Apr 1 3
B Sep 1 3
B Sep 1 3

【问题讨论】:

  • B 的 3 怎么样?
  • @AmitVerma 逻辑是“flag=1 的不同月份数”,所以对于 B,它是 3。

标签: sql sql-server


【解决方案1】:

很遗憾,您不能使用COUNT(DISTINC ...) OVER (),但这是一种解决方法


with
cte as
(
    select  *,
            dr = dense_rank() over (partition by [Group], flag order by [TradeMonth])
    from    yourtable
)
select  [Group], [TradeMonth], flag,
        max(case when flag = 1 then dr end) over (partition by [Group])
from    cte

dbfiddle demo

【讨论】:

    【解决方案2】:

    试试这个

    create table #test([Group] varchar(1), TradeMon Varchar(10), Flag int)
    insert into #test values ('A', 'Jan', 1),('A', 'Mar', 1),('A', 'Mar', 0),('A', 'Jun', 0),('B', 'Feb', 1),('B', 'Apr', 1),('B', 'Sep', 1),('B', 'Sep', 1)
    
    
    With distinctCount AS
    (
        SELECT [group], COUNT(1)DistinctCount
        FROM
        (
            select distinct  [group], TradeMon
            from #test
            where flag=1
        )T GROUP BY [group]
    )
    SELECT T.[GROUP], T.TradeMon, T.Flag, DC.DistinctCount
    FROM #test T
    INNER JOIN distinctCount DC ON  (T.[GROUP] = DC.[Group])
    

    【讨论】:

      【解决方案3】:

      你实际上可以用一个表达式来做到这一点:

      select t.*,
             (dense_rank() over (partition by group
                                 order by (case when flag = 1 then trademonth end)
                                ) +
              dense_rank() over (partition by group
                                 order by (case when flag = 1 then trademonth end) desc
                                ) -
              (1 + min(flag) over (partition by trademonth))
             ) as num_unique_flag_1        
      from t;
      

      这里的逻辑是什么? dense_rank() 升序和降序的总和比不同值的数量多一。

      在正常情况下(即计算不同月份的数量),您只需减去 1。

      但是,在这种情况下,您将 0 值视为NULL。这些仍然被计算在内,但只有其中一个。因此,您可以根据 0 值的存在减去 1 或 2。瞧!结果是标志为 1 的不同月份的数量。

      【讨论】:

      • (1 = min(flag) over (partition by trademonth) 不太对劲
      • @松鼠。 . .谢谢你。那应该是现在是+
      猜你喜欢
      • 2012-11-08
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 2013-04-21
      • 1970-01-01
      相关资源
      最近更新 更多