SQL Server,计数连续几周的记录已进入前5名

时间:2015-07-08 20:46:43

标签: sql sql-server sql-server-2012

我有这个复杂的查询:

SELECT rs.Name, rs.sumhits, rs.weeknumber from(
    SELECT Name, weeknumber, sum(hits) as sumhits, Rank()
    over (Partition By weeknumber ORDER BY sum(hits) desc) AS Rank
FROM
(
    SELECT
    Name,
    DATEDIFF
    (
        day,
        (SELECT DATEADD(wk, DATEDIFF(wk,0,(select min(Table2.date) from Table2)), 0)),
        (Table2.date)
    ) / 7 as weeknumber,
    hits
    FROM Table1
    INNER JOIN Table2 on Table1.nameId = Name.Id
) as a
GROUP BY
Name,
weeknumber
)
rs where rank <= 5
order by weeknumber desc

为我提供了每周最“点击”的前五名“。”

我想补充另一个字段,计算连续周数,本周前五名中的每个名字都在前五名。因此,如果本周前五名中的名字不在上周,则另一列的值为1,如果本周前五名中的名称也在前两周的前五名中,则值为3,等等

实现这一目标的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

您可以将您的查询视为CTE,并在后续CTE或最终SELECT中添加更多信息:

这样的事情:

repeat.for="advert in adverts"

但是 - 正如已经评论过的那样 - 您的查询似乎是“可增强的”:-)也许您发布样本数据和预期结果......

答案 1 :(得分:0)

如果我理解正确,您的基础数据如下:

SELECT Name, dateadd(day, 1 - datepart(dow, date), date) as weekstart,
       sum(hits) as numhits,
       rank() over (partition by dateadd(day, 1 - datepart(dow, date), date)
                    order by sum(hits) desc) as ranking,
       (case when rank() over (partition by dateadd(day, 1 - datepart(dow, date), date)
                    order by sum(hits) desc) <= 5
              then 1 else 0 end) as Top5
FROM Table1 INNER JOIN
     Table2
     on Table1.nameId = Name.Id
GROUP BY Name, dateadd(day, 1 - datepart(dow, date), date);

这会按周提供点击量以及排名。现在我们可以问前五名连续几周的问题。

with cte as (
      SELECT Name, dateadd(day, 1 - datepart(dow, date), date) as weekstart,
             sum(hits) as hits,
             rank() over (partition by dateadd(day, 1 - datepart(dow, date), date)
                          order by sum(hits) desc) as ranking
      FROM Table1 INNER JOIN
           Table2
           on Table1.nameId = Name.Id
      GROUP BY Name, dateadd(day, 1 - datepart(dow, date), date)
     )
select cte.name, cte.numhits,
       ranking,
       (case when ranking <= 5 then Num5s else 0 end) as Num5s
from (select t.*,
             count(*) over (partition by name, grp
                            order by weekstart) as Num5s
      from (select cte.*,
                   (row_number() over (partition by name order by weekstart) -
                    row_number() over (partition by name, top5 order by weekstart)
                   ) as grp
            from cte 
           ) t
     ) t;

逻辑相当复杂。最里面的子查询为每个名称定义一个组,其中grp指定名称在前5名和不在名称时的句点的常量值。中间子查询枚举这些值,外部只是做一些逻辑来返回top5的正确信息。

此查询未经测试,但如果您使用某些数据设置SQL Fiddle,我可以对其进行测试。