MySQL每天的总和

时间:2017-05-03 09:04:07

标签: mysql sql

这与此链接上的帖子有关:

MySQL : sum of every day

datetime (datetime)  count (int)
2012-12-27 09:22:15    5
2012-12-27 18:20:15    4
2012-12-27 23:19:15    3
2012-12-26 13:45:15    8
2012-12-26 04:56:15    7
2012-12-25 01:50:15    2
2012-12-25 12:02:15    1

我想总结每天的COUNT,但不仅仅是那些有入境的日子,还有那些没有入场的日子。

SELECT    DATE(datetime) as DATE, SUM(`count`) totalCOunt
FROM      tableName
GROUP BY  DATE(datetime)

以上代码仅在有入境的那些日子返回我。

假设我想在2016年4月到2017年2月之间获得每天的总计数,我该怎么做?谢谢。例如:

2012-12-25     25
2012-12-26     NULL --> because there is no entry

2 个答案:

答案 0 :(得分:0)

如下面的代码所示。您可以创建日历表。我们根据需要为我们提供准确的日历。 进入该日历表。

DROP TABLE IF EXISTS time_dimension;

CREATE TABLE time_dimension (
        id                      INTEGER PRIMARY KEY,  -- year*10000+month*100+day
        db_date                 DATE NOT NULL,
        year                    INTEGER NOT NULL,
        month                   INTEGER NOT NULL, -- 1 to 12
        day                     INTEGER NOT NULL, -- 1 to 31
        quarter                 INTEGER NOT NULL, -- 1 to 4
        week                    INTEGER NOT NULL, -- 1 to 52/53
        day_name                VARCHAR(9) NOT NULL, -- 'Monday', 'Tuesday'...
        month_name              VARCHAR(9) NOT NULL, -- 'January', 'February'...
        holiday_flag            CHAR(1) DEFAULT 'f' CHECK (holiday_flag in ('t', 'f')),
        weekend_flag            CHAR(1) DEFAULT 'f' CHECK (weekday_flag in ('t', 'f')),
        event                   VARCHAR(50),
        UNIQUE td_ymd_idx (year,month,day),
        UNIQUE td_dbdate_idx (db_date)

) Engine=MyISAM;

DROP PROCEDURE IF EXISTS fill_date_dimension;
DELIMITER //
CREATE PROCEDURE fill_date_dimension(IN startdate DATE,IN stopdate DATE)
BEGIN
    DECLARE currentdate DATE;
    SET currentdate = startdate;
    WHILE currentdate < stopdate DO
        INSERT INTO time_dimension VALUES (
                        YEAR(currentdate)*10000+MONTH(currentdate)*100 + DAY(currentdate),
                        currentdate,
                        YEAR(currentdate),
                        MONTH(currentdate),
                        DAY(currentdate),
                        QUARTER(currentdate),
                        WEEKOFYEAR(currentdate),
                        DATE_FORMAT(currentdate,'%W'),
                        DATE_FORMAT(currentdate,'%M'),
                        'f',
                        CASE DAYOFWEEK(currentdate) WHEN 1 THEN 't' WHEN 7 then 't' ELSE 'f' END,
                        NULL);
        SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY);
    END WHILE;
END
//
DELIMITER ;

TRUNCATE TABLE time_dimension;

CALL fill_date_dimension('2000-01-01','2018-01-01');

创建该日历表后,您可以在下面写下查询,它将解决您的问题。

SELECT COUNT(datetime) ,DB_DATE FROM time_dimension TD
LEFT JOIN TABLENAME TN ON DATE(TN.datetime)=TD.db_date
WHERE TD.DB_DATE BETWEEN '2017-05-01' AND '2017-05-30'
GROUP BY  DATE(DB_DATE);

希望这会有所帮助。

答案 1 :(得分:0)

请尝试以下方法......

DROP PROCEDURE IF EXISTS SumCountAllDays;

DELIMITER //
    CREATE PROCEDURE SumCountAllDays( startDate DATE,
                                      endDate DATE )
    BEGIN
        DECLARE daysCount INT;
        DECLARE daysIndex INT DEFAULT 0;

        SELECT DATEDIFF( endDate,
                         startDate )
        INTO daysCount;

        SET @selectStatementString := CONCAT( "SELECT allDays.intervalDate AS `Date`,",
                                              "       COALESCE( SUM( `count` ), 0 ) AS totalCount ",
                                              "FROM ( SELECT '",
                                              startDate,
                                              "' AS intervalDate" );

        daysLister : LOOP
            SET daysIndex = daysIndex + 1;
            IF daysIndex <= daysCount THEN
                SET @selectStatementString := CONCAT( @selectStatementString,
                                                      " UNION SELECT '",
                                                      DATE_ADD( startDate,
                                                                INTERVAL daysIndex DAY ),
                                                      "'" );
                ITERATE daysLister;
            END IF;
            LEAVE daysLister;
        END LOOP daysLister;

        SET @selectStatementString := CONCAT( @selectStatementString,
                                              " ) AS allDays ",
                                              "LEFT JOIN tableName ON allDays.intervalDate = DATE( `datetime` ) ",
                                              "GROUP BY allDays.intervalDate;" );

        PREPARE selectStatement FROM @selectStatementString;
        EXECUTE selectStatement;
        DEALLOCATE PREPARE selectStatement;
   END //
DELIMITER ;

当您摆弄代码并希望删除旧版本时,第一行非常方便。

其余代码会创建一个过程,在调用并传递相关时段的开始日期和结束日期时,使用DATEDIFF()来计算startDate和{之间的天数{1}},将值存储在endDate

然后,该过程将daysCount初始化为最终语句的第一部分。第一部分以一系列@selectStatementString语句中的第一部分结束,这些语句用于选择SELECTstartDate之间的每个日期。 endDate初始值的SELECT是由所有这些日期的联合形成的字段的名称startDate

循环然后为每个日期附加intervalDate,这些日期是根据循环索引SELECT计算的。

daysIndex运算符用于在每个生成日期执行垂直连接。

UNION完成后,语句的其余部分将附加到语句到目前为止。如果LOOPstartDateendDate2012-02-13,那么我们现在会有以下声明......

2012-02-15

我针对使用以下脚本创建的测试数据库测试了我的语句...

SELECT allDays.intervalDate AS `Date`,
       COUNT( `count` ) AS totalCount
FROM ( SELECT '2012-02-13' AS intervalDate
       UNION
       SELECT '2012-02-14'
       UNION
       SELECT '2012-02-15' ) AS allDays
LEFT JOIN tableName ON allDays.intervalDate = DATE( `datetime` )
GROUP BY allDays.intervalDate;

我使用以下声明调用了该程序......

CREATE TABLE tableName
(
    `datetime`   DATETIME,
    `count`      INT
);
INSERT INTO tableName ( `datetime`,
                        `count` )
VALUES ( '2012-12-27 09:22:15', 5 ),
       ( '2012-12-27 18:20:15', 4 ),
       ( '2012-12-27 23:19:15', 3 ),
       ( '2012-12-26 13:45:15', 8 ),
       ( '2012-12-26 04:56:15', 7 ),
       ( '2012-12-25 01:50:15', 2 ),
       ( '2012-12-25 12:02:15', 1 );

如果您有任何问题或意见,请随时发表评论。