如何在sql中显示一周一周

时间:2014-06-01 18:21:06

标签: mysql datetime time-series aggregate

我需要在一周内显示GP总和的两个计算列,在前一个

中显示另一列

我认为我的方式是正确的,但我错过了一些东西

我想让我的结果像这样::

| WEEK | JP | AUS | GB |

| PREV | 22 | 32 | 23 |

| CUR | 12 | 15 | 12 |

我的sql是这个我相信我可能需要转动数据

SELECT 
  (SUM(`GP`), `gptw`) 
FROM
  (SELECT 
    `GP`,
    `Country` 
  FROM
    `Finance` 
  WHERE DATE >= CURDATE() - INTERVAL DAYOFWEEK(CURDATE()) + 6 DAY 
    AND DATE < CURDATE() - INTERVAL DAYOFWEEK(CURDATE()) - 1 DAY 
  GROUP BY `Country`) AS lastweeek 
  INNER JOIN 
    (SELECT 
      SUM(`GP`) AS `gptw`,
      `Country` 
    FROM
      Finance 
    WHERE DATEDIFF(NOW(), `date`) < 4 
    GROUP BY `Country`) AS `thisweek` 

1 个答案:

答案 0 :(得分:5)

Nitpick:DATE是一个糟糕的列名选择,因为它是一个保留的SQL词。

这里有四个逻辑层次。

首先,你需要有工作逻辑来确定每一天的哪一周。

其次,您需要选择正确的DATE值范围。

第三,你需要使GROUP BY逻辑正确。

第四,你需要将结果集转动到本周和上周进入同一行。这种旋转应该成为另一个问题的主题。


首先,此表达式会将任何DATETIME值转换为前一个星期日。

FROM_DAYS(TO_DAYS(value) -MOD(TO_DAYS(value) -1, 7))

其次,您需要选择两周(上周和本周)

WHERE `DATE` >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 7 DAY
  AND `DATE` <  FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) + INTERVAL 7 DAY

这样的日期范围从上周日前的星期日开始,到本星期日之后的星期日结束前的两个星期。


第三,你需要正确分组。在您的架构中,按周和按国家/地区分组。它会是这样的:

SELECT  SUM(`GP`) AS GP,
       `Country`,
        FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7)) AS week_beginning
  FROM `Finance`
 WHERE `DATE` >= FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) - INTERVAL 7 DAY
   AND `DATE` <  FROM_DAYS(TO_DAYS(NOW()) -MOD(TO_DAYS(NOW()) -1, 7)) + INTERVAL 7 DAY
  GROUP BY `Country`, FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7))
  ORDER BY `Country`, FROM_DAYS(TO_DAYS(`DATE`) -MOD(`DATE`) -1, 7))

这将为每个国家/地区提供两行,一行用于一周前的week_beginning,另一行用于当前周。这可以帮到你。如果没有,您可以转动此查询的结果,以按您希望的方式排列行。那应该是另一个问题的主题。


最后,如果您可以在MySQL实例中定义存储函数,则应定义函数TRUNC_SUNDAY。然后你可以像这样更容易地编写你的查询:

SELECT  SUM(`GP`) AS GP,
       `Country`,
        TRUNC_SUNDAY(`DATE`) AS week_beginning
  FROM `Finance`
 WHERE `DATE` >= TRUNC_SUNDAY(NOW()) - INTERVAL 7 DAY
   AND `DATE` <  TRUNC_SUNDAY(NOW())  + INTERVAL 7 DAY
  GROUP BY `Country`, TRUNC_SUNDAY(`DATE`)
  ORDER BY `Country`, TRUNC_SUNDAY(`DATE`)

这是用于定义所需存储的TRUNC_SUNDAY函数的SQL代码:

DELIMITER $$
DROP FUNCTION IF EXISTS `TRUNC_SUNDAY`$$    
CREATE FUNCTION `TRUNC_SUNDAY`(datestamp DATETIME) 
    RETURNS DATE
    NO SQL
    DETERMINISTIC
    COMMENT 'returns preceding Sunday'
RETURN FROM_DAYS(TO_DAYS(datestamp) -MOD(TO_DAYS(datestamp) -1, 7))$$
DELIMITER ;

您可以在此处找到此技术的详细说明,包括TRUNC_MONDAY函数。如果您的工作日定义为星期一而不是星期日,则您需要TRUNC_MONDAY功能。 http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/