【问题标题】:How to merge 2 or more date range into 1如何将 2 个或更多日期范围合并为 1
【发布时间】:2016-02-25 11:06:58
【问题描述】:

我使用的是 MySQL 5.6

我正在处理一个复杂的业务问题。

无论如何,我试着用这个例子来简单地解释问题。

有一个包含这些记录的表:

  1. Acct-1 2016-01-01 2016-01-07

  2. Acct-1 2016-01-05 2016-01-11

  3. Acct-1 2016-01-18 2016-01-24

  4. Acct-1 2016-02-02 2016-02-08

  5. Acct-1 2016-02-07 2016-02-13

第一列是帐号。在此示例中,所有帐号都是相同的帐号。第 2 列和第 3 列是日期范围。所有日期范围正好是 7 天。

我想让这个表格更漂亮,将重叠范围“合并”到一个日期范围中。

所以,record-1 和 record-2 应该合并在一起成为:

Acct-1 2016-01-01 2016-01-11

Record-3 是独立的,无需与其他人合并。

Record-4 和 record-5 应该合并在一起成为:

Acct-1 2016-02-02 2016-02-13

最后,每个帐户都应该有不重叠日期范围的记录。

注意,有时我们必须合并 2 或 3 或 4 条记录,否则取决于重叠。表中有许多不同的帐号。

如何使用 SQL 语句做到这一点?

可以创建临时视图来达到目的。

干杯,

阿尔文

【问题讨论】:

  • 我们也可以使用存储过程吗?

标签: mysql


【解决方案1】:

这里有一个使用用户变量的解决方案。已使用您提供的数据进行验证,我插入了更多数据进行验证。

为了永久保存查询结果并保持以后可以访问,将结果写入表 tbl_new。

完整演示>>

SQL:

-- data preparation
create table tbl(acct varchar(100), start_date date, end_date date);
insert into tbl values
('Acct-1', '2016-01-01', '2016-01-07'),
('Acct-1', '2016-01-05', '2016-01-11'),
('Acct-1', '2016-01-18', '2016-01-24'),
('Acct-1', '2016-02-02', '2016-02-08'),
('Acct-1', '2016-02-07', '2016-02-13'),
('Acct-2', '2016-01-01', '2016-01-07'),
('Acct-2', '2016-01-18', '2016-01-24'),
('Acct-2', '2016-01-02', '2016-02-08');


SELECT * FROM tbl;

-- Need queries
SET @last_acct = '', @last_start_date = '1970-01-01', @last_end_date = '9999-12-31', @group = 1;

CREATE TABLE tbl_new (acct varchar(100), start_date date, end_date date);

INSERT INTO tbl_new 
SELECT 
    acct,
    MIN(start_date) start_date,
    MAX(end_date) end_date
FROM
(
    SELECT
        acct, 
        start_date, 
        end_date,
        CASE 
            WHEN 
                acct = @last_acct AND start_date <= @last_end_date 
            THEN 
                @group
            ELSE
                @group := @group + 1
        END group_num, 
        @last_acct := acct,
        @last_start_date := start_date,
        @last_end_date := end_date
    FROM
        tbl
) tbl2
GROUP BY group_num;

SELECT * FROM tbl_new;

输出:

mysql> SELECT * FROM tbl;
+--------+------------+------------+
| acct   | start_date | end_date   |
+--------+------------+------------+
| Acct-1 | 2016-01-01 | 2016-01-07 |
| Acct-1 | 2016-01-05 | 2016-01-11 |
| Acct-1 | 2016-01-18 | 2016-01-24 |
| Acct-1 | 2016-02-02 | 2016-02-08 |
| Acct-1 | 2016-02-07 | 2016-02-13 |
| Acct-2 | 2016-01-01 | 2016-01-07 |
| Acct-2 | 2016-01-18 | 2016-01-24 |
| Acct-2 | 2016-01-02 | 2016-02-08 |
+--------+------------+------------+
8 rows in set (0.00 sec)

mysql>
mysql> -- Need queries
mysql> SET @last_acct = '', @last_start_date = '1970-01-01', @last_end_date = '9999-12-31', @group = 1;
Query OK, 0 rows affected (0.00 sec)

mysql>
mysql> CREATE TABLE tbl_new (acct varchar(100), start_date date, end_date date);
Query OK, 0 rows affected (0.01 sec)

mysql>
mysql> INSERT INTO tbl_new
    -> SELECT
    ->     acct,
    ->     MIN(start_date) start_date,
    ->     MAX(end_date) end_date
    -> FROM
    -> (
    ->     SELECT
    ->         acct,
    ->         start_date,
    ->         end_date,
    ->         CASE
    ->             WHEN
    ->                 acct = @last_acct AND start_date <= @last_end_date
    ->             THEN
    ->                 @group
    ->             ELSE
    ->                 @group := @group + 1
    ->         END group_num,
    ->         @last_acct := acct,
    ->         @last_start_date := start_date,
    ->         @last_end_date := end_date
    ->     FROM
    ->         tbl
    -> ) tbl2
    -> GROUP BY group_num;

Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql>
mysql> SELECT * FROM tbl_new;
+--------+------------+------------+
| acct   | start_date | end_date   |
+--------+------------+------------+
| Acct-1 | 2016-01-01 | 2016-01-11 |
| Acct-1 | 2016-01-18 | 2016-01-24 |
| Acct-1 | 2016-02-02 | 2016-02-13 |
| Acct-2 | 2016-01-01 | 2016-01-07 |
| Acct-2 | 2016-01-02 | 2016-02-08 |
+--------+------------+------------+
5 rows in set (0.00 sec)

【讨论】:

  • 实际上,我更喜欢使用 VIEW 来实现这一点,因为我必须将视图与其他表连接起来才能获取其他一些信息。我不太确定变量是否可以在创建视图语句中使用。
  • @AlvinSIU 更新了发布的解决方案,将结果保存到表格中。
  • @AlvinSIU 新解决方案是否符合您的期望?
  • 其实我需要一个create view语句,这样用户就可以点击view来获取结果。用户不知道编写 SQL 的细节。我们的表格每天都会更新,每天都会添加记录。使用这种方法,我必须在每天刷新 tbl 后安排另一个作业来重新创建 tbl_new。也许我必须考虑一些解决方法。
  • @DylanSu 漂亮的解决方案!
猜你喜欢
  • 1970-01-01
  • 2020-02-28
  • 2013-11-09
  • 2016-02-12
  • 2015-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多