【问题标题】:Get dates between two dates获取两个日期之间的日期
【发布时间】:2018-01-11 10:28:49
【问题描述】:

我有两张这样的表:

表 1

emp_leave_summary(id,emp_id,leave_from_date,leave_to_date,leave_type)

表2

emp_leave_daywise(id,emp_id,leave_date,leave_type)

我想从 Table1 中选择 emp_id, leave_type 并插入 Table2

例如: 在 table1 我有这个

id,emp_id,leave_from_date,leave_to_date,leave_type
 1, 12345,2017-07-01     ,2017-07-03   ,Sick Leave

在表2中,我想要这个

id,emp_id,leave_date,leave_type
 1,12345,2017-07-01,Sick Leave
 2,12345,2017-07-02,Sick Leave
 3,12345,2017-07-03,Sick Leave

带有样本数据的表结构

    CREATE TABLE `emp_leave_summary` (
  `id` int(11) NOT NULL,
  `emp_id` int(11) NOT NULL,
  `leave_from_date` date NOT NULL,
  `leave_to_date` date NOT NULL,
  `leave_type` varchar(30) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `emp_leave_summary` (`id`, `emp_id`, `leave_from_date`, `leave_to_date`, `leave_type`) VALUES
(1, 123, '2017-02-01', '2017-02-15', 'Earned Vacation Leave'),
(2, 123, '2017-07-12', '2017-07-26', 'Earned Vacation Leave'),
(3, 456, '2017-03-20', '2017-04-20', 'Earned Vacation Leave'),
(4, 789, '2017-01-15', '2017-02-23', 'Earned Vacation Leave'),
(5, 789, '2017-02-26', '2017-02-27', 'Sick Leave');

CREATE TABLE `emp_leave_daywise` (
  `id` int(11) NOT NULL,
  `emp_id` int(11) NOT NULL,
  `leave_date` date NOT NULL,
  `leave_type` varchar(30) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


ALTER TABLE `emp_leave_daywise`
ADD PRIMARY KEY (`id`),
ADD KEY `emp_id` (`emp_id`),
ADD KEY `leave_date` (`leave_date`),
ADD KEY `leave_type` (`leave_type`);


ALTER TABLE `emp_leave_summary`
ADD PRIMARY KEY (`id`),
ADD KEY `emp_id` (`emp_id`),
ADD KEY `leave_type` (`leave_type`),
ADD KEY `leave_from_date` (`leave_from_date`),
ADD KEY `leave_to_date` (`leave_to_date`);

【问题讨论】:

标签: mysql sql


【解决方案1】:

试试:

    select * from 
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_date from
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where selected_date between '2012-02-10' and '2012-02-15'

-对于未来近 300 年的日期范围。

来自How to get list of dates between two dates in mysql select query

【讨论】:

  • 谢谢你,非常感谢,但我希望在输出中也有其他列。像这样id,emp_id,leave_date,leave_type
【解决方案2】:

我已经设法使用以下解决方案获得首选输出

第一步

创建一个日历表并插入日期(所有可能需要的日期)类似这样的东西

CREATE TABLE `db_calender` (
        `c_date` date NOT NULL);

然后将日期插入日历表中,为了方便插入,我使用了这个How to populate a table with a range of dates? 中回答的程序,感谢Leniel Macaferi 先生。

    DROP PROCEDURE IF EXISTS filldates;
DELIMITER |
CREATE PROCEDURE filldates(dateStart DATE, dateEnd DATE)
BEGIN
  WHILE dateStart <= dateEnd DO
    INSERT INTO tablename (_date) VALUES (dateStart);
    SET dateStart = date_add(dateStart, INTERVAL 1 DAY);
  END WHILE;
END;

| 分隔符; CALL 填写日期('2017-02-01','2017-07-31');

然后我尝试在此查询下方获取首选输出

    SELECT
     els.*, c.c_date
FROM
    emp_leave_summary els
     JOIN db_calender c ON c.c_date BETWEEN els.leave_from_date AND els.leave_to_date 
ORDER BY
     els.id,c.c_date

感谢大家的贡献和支持。

【讨论】:

    【解决方案3】:

    感谢您的架构。它使处理您的问题变得容易。 我稍微更改了您的架构以使用 auto_increment

    CREATE TABLE `emp_leave_summary` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `emp_id` int(11) NOT NULL,
      `leave_from_date` date NOT NULL,
      `leave_to_date` date NOT NULL,
      `leave_type` varchar(30) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    INSERT INTO `emp_leave_summary` (`emp_id`, `leave_from_date`, `leave_to_date`, `leave_type`) VALUES
    ( 123, '2017-02-01', '2017-02-15', 'Earned Vacation Leave'),
    ( 123, '2017-07-12', '2017-07-26', 'Earned Vacation Leave'),
    ( 456, '2017-03-20', '2017-04-20', 'Earned Vacation Leave'),
    ( 789, '2017-01-15', '2017-02-23', 'Earned Vacation Leave'),
    ( 789, '2017-02-26', '2017-02-27', 'Sick Leave');
    
    CREATE TABLE `emp_leave_daywise` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `emp_id` int(11) NOT NULL,
      `leave_date` date NOT NULL,
      `leave_type` varchar(30) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    这里我在 emp_leave_daywise 表上添加了一个唯一约束,因为 id 整数上的主键并不能确保记录不重复。

    ALTER TABLE `emp_leave_daywise`
    ADD UNIQUE KEY `emp_leave_daywise_unique_key` (`emp_id`,`leave_date`,`leave_type`),
    ADD KEY `emp_id` (`emp_id`),
    ADD KEY `leave_date` (`leave_date`),
    ADD KEY `leave_type` (`leave_type`);
    

    emp_leave_summary 的唯一键需要考虑一下。 例如……您是否允许包含重叠日期范围的摘要? ...

    ALTER TABLE `emp_leave_summary`
    ADD UNIQUE KEY `emp_leave_summary_unique_key` (`emp_id`,`leave_from_date`),
    ADD KEY `emp_id` (`emp_id`),
    ADD KEY `leave_type` (`leave_type`),
    ADD KEY `leave_from_date` (`leave_from_date`),
    ADD KEY `leave_to_date` (`leave_to_date`);
    

    现在使用现有数据的左连接进行数据提取。

    /*
        insert any missing records using a left join on existing records
        */
    insert into emp_leave_daywise ( emp_id, leave_date, leave_type )
    select `new`.* from 
    ( 
        select summary.emp_id, dates.date_ leave_date, summary.leave_type 
        from emp_leave_summary summary
        inner join (
        /* 
            get dates to match against
            https://stackoverflow.com/questions/9295616/how-to-get-list-of-dates-between-two-dates-in-mysql-select-query
            */
            select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) date_ from
            ( select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
            ( select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
            ( select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
            ( select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
            ( select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) dates
     on dates.date_ >= summary.leave_from_date 
     and dates.date_ <= summary.leave_to_date
     ) `new`
     left join emp_leave_daywise old
     on `new`.emp_id = old.emp_id
     and `new`.leave_date = old.leave_date 
     and `new`.leave_type = old.leave_type 
     where old.id is null ;
    
     select * from emp_leave_daywise order by leave_date, emp_id;
    

    根据给定的数据返回 104 行

     id emp_id  leave_date  leave_type
     1  789 2017-01-15  Earned Vacation Leave
     2  789 2017-01-16  Earned Vacation Leave
     3  789 2017-01-17  Earned Vacation Leave
     4  789 2017-01-18  Earned Vacation Leave
     5  789 2017-01-19  Earned Vacation Leave
     6  789 2017-01-20  Earned Vacation Leave
     ...
     102    123 2017-07-24  Earned Vacation Leave
     103    123 2017-07-25  Earned Vacation Leave
     104    123 2017-07-26  Earned Vacation Leave
    

    日期范围创建SQL从这里How to get list of dates between two dates in mysql select query

    【讨论】:

    • 非常感谢它工作得很好。我喜欢ADD UNIQUE KEY emp_leave_daywise_unique_key (emp_id,leave_date,leave_type),,它可以确保没有重复的条目。
    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 2017-06-03
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多