存储过程仅提供有限数量的结果

时间:2018-04-25 11:27:30

标签: mysql

我的StoredProcedure只给出了结果中最大行数等于表格的条目数量。

所以call SP_Dashboard_getTransactionsPerDay("2018-03-19", "2018-04-25")会给我:

date      | total
-----------------
2018-03-19| 0
2018-03-19| 0

如果event表中有2个条目,而不是完整的38个请求日期。如果event中有6个条目,则同一调用会给我6行;如果event中至少有38个或更多条目,则会给我38个行。

即使event表格中没有条目,有没有办法获得所有请求日期的结果?

我的SP看起来如下:

CREATE PROCEDURE `SP_Dashboard_getTransactionsPerDay`(STARTDATE DATE,ENDDATE DATE)
BEGIN


set @i := -1;

SELECT
  DATE(ADDDATE(STARTDATE, INTERVAL @i:=@i+1 DAY)) AS date,
  IFNULL(
      (
        SELECT
          COUNT(*) FROM event AS m2
        WHERE
          DATE(m2.created_at) = DATE(ADDDATE(STARTDATE, INTERVAL @i DAY))
          AND `m2`.`status` = 'ok'
      ),
      0) AS total
FROM
  event AS m1;
HAVING
  @i < DATEDIFF(ENDDATE, STARTDATE);
END

表DDL:

CREATE TABLE `event` (
  `id` int(15) NOT NULL AUTO_INCREMENT,
  `status` enum('new','ok','error') COLLATE utf8_bin NOT NULL DEFAULT 'new',
  `created_at` datetime NOT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

1 个答案:

答案 0 :(得分:0)

添加日历/日期表通过将以下内容添加到我的数据库中解决了这个问题:

新表:

-- -----------------------------------------------------
-- Table `dates`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `dates`;

CREATE TABLE `dates` (
  `date` DATE NOT NULL,
  PRIMARY KEY (`date`)
)
ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COLLATE = utf8_bin;

自动填充新表的存储过程:

-- -----------------------------------------------------
-- StoredProcedure `SP_filldates`
-- -----------------------------------------------------
DROP PROCEDURE IF EXISTS SP_filldates;

DELIMITER $$
CREATE PROCEDURE SP_filldates(STARTDATE DATE, ENDDATE DATE)
  BEGIN
    WHILE STARTDATE <= ENDDATE DO
      INSERT INTO dates (date) VALUES (STARTDATE);
      SET STARTDATE = date_add(STARTDATE, INTERVAL 1 DAY);
    END WHILE;
  END;
$$
DELIMITER ;

CALL SP_filldates('2018-01-01', '2018-12-31');

并修改了我最初发布的存储过程:

-- -----------------------------------------------------
-- StoredProcedure `SP_Dashboard_getTransactionsPerDay`
-- -----------------------------------------------------
DROP PROCEDURE
IF EXISTS SP_Dashboard_getTransactionsPerDay;

DELIMITER $$


CREATE PROCEDURE SP_Dashboard_getTransactionsPerDay(
  STARTDATE DATE,
  ENDDATE   DATE
)
  BEGIN

    SET @i := -1;

    SELECT
      DATE(ADDDATE(STARTDATE, INTERVAL @i := @i + 1 DAY)) AS date,
      IFNULL(
          (
            SELECT COUNT(*)
            FROM event AS m2
            WHERE
              DATE(m2.created_at) = DATE(ADDDATE(STARTDATE, INTERVAL @i DAY))
              AND `m2`.`status` = 'ok'
          ),
          0
      ) AS total
    FROM
      dates AS m1
    HAVING
      @i < DATEDIFF(ENDDATE, STARTDATE);

  END$$

DELIMITER ;

此修复程序适用于最多365行的所有请求,因为在这种情况下,日期表只包含365个条目。如果需要更多结果,则日期表必须包含更多日期。