如何计算MySQL中每周符合条件的行?

时间:2015-07-14 20:47:39

标签: mysql group-by

我有一个存储票据请求的表,并记录请求和解决的日期。

我想制作一个查询,每周会显示系统中有多少未解决的故障单。

问题是如果我将请求的日期用作组标准,那么未解决超过一周的故障单不会被计算两次。我想确保任何未解决的票证超过我的团队规模,并根据需要多次提供其数量。

例如,使用以下数据:

id  requested   resolved
==  ==========  ==========
1   2015-07-01  2015-07-02
2   2015-07-01  NULL
3   2015-07-08  2015-07-10
4   2015-07-08  NULL

第一(26)和第二周(27)各有两个请求。每周有一个已解决的请求和一个未解决的请求,因此查询结果应显示第一周1未解析,第二周未解析2。 (未来一周内具有解决方案日期的项目也算作未解决,但出于简化此示例的目的,我只显示空日期。)

我希望结果显示:

year   week    # unresolved
====   ====    ============
2015   26      1
2015   27      2

到目前为止我的查询:

SELECT
    YEAR(requested) `year`,
    WEEK(requested, 5) `week`,
    COUNT(id) `# unresolved`
FROM
    tickets
WHERE
    WEEK(requested) < WEEK(resolved)
    OR resolved IS NULL
GROUP BY `Year`, `Week`;

每周仅显示1张未解决的票证:

year  week  # unresolved  
====  ====  ============
2015  26    1               
2015  27    1               

我应该考虑什么来适当地修改此查询?

http://sqlfiddle.com/#!9/90782/1/0

修改

作为附加信息,这是一个相对简单的查询,为其提供任何特定的一周来检查:

SELECT
    COUNT(id) `# unresolved`
FROM
    tickets
WHERE
    WEEK(requested) <= WEEK('2015-07-01')
    AND
    (
        WEEK(resolved) > WEEK('2015-07-01')
        OR resolved IS NULL
    );

通过更改输入周,可以获得任何感兴趣的一周的未解决的门票数量。我的目标是创建一个查询,按周对所有可用数据进行分组,而不是修改此查询以获得单周结果。

4 个答案:

答案 0 :(得分:1)

(注意:我正在展示我的思考过程,但您只需要在此答案中进行最终查询)

(注2:检查sqlfiddle here

我会查看所请求的故障单并将故障单解决为两种不同类型的事件,所以

select requested eventDate, 1 ticketChange from table

会为每张请求的机票提供1个计数和

select resolved eventDate, -1 ticketChange from table

会给每个已解决的机票一个-1计数。如果我将这两个查询联合起来,我会得到一个日期列表,其中包含+1和-1,表示是否添加或解决了故障单。所以我每周都可以通过

获得一个未解决的问题
    select year(eventDate) myYear, week(eventDate) myWeek, sum(ticketChange) totTicketChange
    from (select requested eventDate, 1 ticketChange from table union all
          select resolved eventDate, -1 ticketChange from table where resolved is not null)
    group by year(eventDate) asc, week(eventDate) asc

但是既然你需要一个累计总数,那么我会定义一个变量@unresolvedCount并在我浏览选择行时递增它:

set @unresolvedCount := 0;
select myYear, myWeek, (@unresolvedCount := @unresolvedCount + totTicketChange) unresolved
  from (select year(eventDate) myYear, week(eventDate) myWeek, sum(ticketChange) totTicketChange
          from (select requested eventDate, 1 ticketChange from tickets union all
                select resolved eventDate, -1 ticketChange from tickets where resolved is not null) TicketEvents
 group by year(eventDate) asc, week(eventDate) asc) TicketCummulative

这正是您想要的。我已经用上面提到的小提琴检查了它,如果你能找到一个更有效的算法去做你想做的事情,我会感到惊讶。我还建议您自己运行每个内部查询,查看其结果,然后逐步解决问题。这将使您深入了解它的工作原理。

如果您希望仅在特定时间段(例如当前年份)获得结果,则根据您的需要,有三种不同的方法。如果您想要计算在此时间段内请求的门票,例如,您不想计算去年请求的门票,即使它们仍未解决或者即使他们今年得到解决,你也可以将最里面的查询改为:

select requested eventDate, 1 ticketChange from tickets where requested >= '2015-01-01' union all
select resolved eventDate, -1 ticketChange from tickets where requested >= '2015-01-01' and resolved is not null

如果您想要计算在给定时间段内请求或解决的故障单,那么您可以将最里面的查询更改为:

select requested eventDate, 1 ticketChange from tickets where requested >= '2015-01-01' union all
select resolved eventDate, -1 ticketChange from tickets where resolved is not null and resolved >= '2015-01-01'

如果您想计算所有门票,只要它们在当前时间段内被请求或解决,或者它们仍未解决(即使它们是3岁),那么您将不得不进行测试日期,在完整查询的最后,让内部查询处理所有票证。

... group by year(eventDate) asc, week(eventDate) asc) TicketCummulative where myYear >= 2015 and myWeek >= 1

答案 1 :(得分:0)

如何将Unresolved设置为MySQL,如下所示

set @preCount = 0;
select ticketsB.Year, ticketsB.Week,
    IF(@preCount=0, @preCount:=Unresolved, @preCount:=@preCount+Unresolved) as Unresolved from (
SELECT
    YEAR(requested) `Year`,
    WEEK(requested, 5) `Week`,
    count(id) `Unresolved`
FROM
    tickets
WHERE
    WEEK(requested) < WEEK(resolved)
    OR resolved IS NULL
GROUP BY `Year`, `Week`) as ticketsB

在此处查看结果http://sqlfiddle.com/#!9/90782/61

基本上,您将先前未解决的计数存储到本地可验证的计数中,然后根据变量中的内容将未解析的计数添加到下一行。

答案 2 :(得分:0)

稀疏的数据集应该得到稀疏的答案,所以这是另一个想到的...

SELECT WEEK(x.requested) wk
     , COUNT(y.id) 
  FROM tickets x 
  JOIN tickets y 
   ON y.id <= x.id 
  AND y.resolved IS NULL 
WHERE x.resolved IS NULL 
GROUP 
   BY WEEK(x.requested);

答案 3 :(得分:-1)

我认为这是一个透视问题。您需要将查询提供给报告日期/周。

SELECT
    YEAR(requested) `Year`,
    WEEK(requested, 5) `Week`,
    COUNT(id) `Qty Unresolved`
FROM
    tickets
WHERE
    WEEK('2015-07-08') <= WEEK(resolved)
    or resolved IS NULL
GROUP BY `Year`, `Week`;