SQL频率计数

时间:2018-03-30 19:38:11

标签: sql-server count frequency

我在SSMS中有一张表:

Id  Date    Value
111 1/1/18  x
111 1/2/18  x
111 1/3/18  y
111 1/4/18  y
111 1/5/18  x
111 1/6/18  x
222 1/3/18  z
222 1/6/18  y
222 1/8/18  y

我想要计算最新值的频率。所以输出将是:

Id  Value  Days
111 x      2   *(for 1/5/18 & 1/6/18)*
222 y      3   *(for 1/6/18 & 1/8/18; Here I assume 1/7/18 is a weekend or holiday.  Even though my table skips the weekend, we still want to count days for the weekend)*

如何做到这一点?非常感谢!

4 个答案:

答案 0 :(得分:1)

尝试:

SELECT COUNT(*) FROM Table1 WHERE Value = 
(
    SELECT Value FROM Table1 WHERE Id = MAX(Id)
)

答案 1 :(得分:1)

我希望你想要这个

select Id, count(Date) as "Days", Value from SSMS
group by ID, Value

如果我错了,请纠正我

答案 2 :(得分:1)

使用lag获取上一行的值,然后使用运行总和来分配组。然后计算第一组中的数字。

select id,val,datediff(day,min(date),max(date))+1 as days
from (select t.*,sum(case when val=prev_val then 0 else 1 end) over(partition by id order by date desc) as grp
      from (select t.*,lag(val) over(partition by id order by date desc) as prev_val
            from tbl t
           ) t
     ) t
where grp=1
group by id,val

答案 3 :(得分:1)

这个答案应该考虑到您所做的周末和假期假设(使用另一个测试用例)。

SELECT
    T.Id, T.val, DATEDIFF(DD, COALESCE(T.MaxSwitch, T.MinMatch, T.MaxDate), T.MaxDate) + 1 AS [Days]
FROM (
    SELECT
        T.Id,
        MAX(CASE WHEN T.LastValue IS NULL THEN T.val ELSE '' END) AS [val],
        MAX(T.Date) AS [MaxDate],
        MAX(CASE WHEN t.val <> t.LastValue THEN T.RunningDate ELSE NULL END) AS [MaxSwitch],
        MIN(CASE WHEN t.val = t.LastValue THEN T.[Date] ELSE NULL END) AS [MinMatch]
    FROM (SELECT *, LAG(val) OVER (PARTITION BY Id ORDER BY DATE DESC) AS LastValue,
        LAG([Date]) OVER (PARTITION BY Id ORDER BY DATE DESC) AS RunningDate FROM @T) T
    GROUP BY 
        T.Id
    ) T

此方法使用LAG来跟踪以前的值和日期,以便它可以确定(1)获得运行匹配的最后一个值,(2)当值切换到最近值时的最新日期,以及(3) )与价值匹配最后日期的最早日期。然后,它计算日期差异以计算表格中跳过天数的优先级(A)切换到最近值的最新日期值,(B)或者如果没有发生切换,那么最早的日期值与最终日期匹配。

以下示例数据:

DECLARE @T TABLE (
    Id INT, [Date] DATE, val VARCHAR(10)
)
INSERT @T VALUES
    ('111', '1/1/18', 'x'),
    ('111', '1/2/18', 'x'),
    ('111', '1/3/18', 'y'),
    ('111', '1/4/18', 'y'),
    ('111', '1/5/18', 'x'),
    ('111', '1/6/18', 'x'),
    ('222', '1/2/18', 'y'),
    ('222', '1/3/18', 'z'),
    ('222', '1/6/18', 'y'),
    ('222', '1/8/18', 'y'),
    ('333', '1/9/18', 'a')

给出以下输出:

Id          val        Days
----------- ---------- -----------
111         x          2 (from OP example)
222         y          3 (from OP example)
333         a          1 (case of single value)