问题
I am looking for a help in transforming below data into the required output. We have data at Item,LOC DAY level data which needs to be transformed to Item,Loc Date Range to reduce the number of records in the table and for other requirements.
Item LOC RP_DATE RP_IND
1003785256 543 2016-11-05 Y
1003785256 543 2016-11-06 Y
1003785256 543 2016-11-07 Y
1003785256 543 2016-11-09 Y
1003785256 543 2016-11-10 Y
1003790365 150 2016-11-05 Y
1003797790 224 2016-11-05 Y
1003797790 224 2016-11-06 Y
1003797790 224 2016-11-07 Y
1003797790 224 2016-11-08 Y
Required Output:
Item LOC RP_ST_DATE RP_END_DATE
1003785256 543 2016-11-05 2016-11-07
1003785256 543 2016-11-09 2016-11-10
1003790365 150 2016-11-05 2016-11-05
1003797790 224 2016-11-05 2016-11-08
回答1:
This approach is for MySQL. It uses a combination variables within an ordered subquery to establish a common starting date for each "range". The CROSS JOIN is used just to initialize the variables, it does not alter the number of rows. Once the common starting date is established then it becomes a simple group by query in the outer query.
SELECT Item, LOC, RP_IND, dr_begin, MAX(RP_DATE) dr_end
FROM (
SELECT
mytable.*
, @fin := CONVERT(IF(@item<=>item AND @loc<=>loc AND DATEDIFF(rp_date, @d)=1, @fin, rp_date), DATE) AS dr_begin
, @item := item
, @loc := loc
, @d := rp_date
FROM mytable CROSS JOIN (SELECT @item:=NULL, @loc:=NULL, @d:=NULL, @fin := NULL) AS init
ORDER BY item, loc, rp_date
) d
GROUP BY Item, LOC, RP_IND, dr_begin
;
+----+------------+-----+--------+------------+---------------------+
| | Item | LOC | RP_IND | dr_begin | dr_end |
+----+------------+-----+--------+------------+---------------------+
| 1 | 1003785256 | 543 | Y | 2016-11-05 | 07.11.2016 00:00:00 |
| 2 | 1003785256 | 543 | Y | 2016-11-09 | 10.11.2016 00:00:00 |
| 3 | 1003790365 | 150 | Y | 2016-11-05 | 05.11.2016 00:00:00 |
| 4 | 1003797790 | 224 | Y | 2016-11-05 | 08.11.2016 00:00:00 |
+----+------------+-----+--------+------------+---------------------+
Note <=> returns 1 if both operands are NULL
See the query working at: http://rextester.com/SEYG96251
#drop table mytable;
CREATE TABLE mytable(
Item INTEGER NOT NULL
,LOC INTEGER NOT NULL
,RP_DATE DATE NOT NULL
,RP_IND VARCHAR(1) NOT NULL
);
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003785256,543,'2016-11-05','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003785256,543,'2016-11-06','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003785256,543,'2016-11-07','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003785256,543,'2016-11-09','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003785256,543,'2016-11-10','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003790365,150,'2016-11-05','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003797790,224,'2016-11-05','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003797790,224,'2016-11-06','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003797790,224,'2016-11-07','Y');
INSERT INTO mytable(Item,LOC,RP_DATE,RP_IND) VALUES (1003797790,224,'2016-11-08','Y');
来源:https://stackoverflow.com/questions/45023270/transform-dates-into-date-range-in-mysql-how-to-handle-gaps-in-the-dates