I have table with data like this
price | date | type |
---|---|---|
1000 | 2021-03-13 | A |
1000 | 2021-03-14 | A |
1000 | 2021-03-15 | A |
1300 | 2021-03-16 | A |
1000 | 2021-03-17 | A |
1300 | 2021-03-18 | A |
1000 | 2021-03-19 | A |
1500 | 2021-03-20 | A |
1500 | 2021-03-21 | A |
1500 | 2021-03-22 | A |
2000 | 2021-03-13 | B |
2000 | 2021-03-14 | B |
2000 | 2021-03-15 | B |
2000 | 2021-03-16 | B |
2000 | 2021-03-17 | B |
I want to query data like this
price | startDate | endDate | type |
---|---|---|---|
1000 | 2021-03-13 | 2021-03-15 | A |
1300 | 2021-03-16 | 2021-03-16 | A |
1000 | 2021-03-17 | 2021-03-17 | A |
1300 | 2021-03-18 | 2021-03-18 | A |
1000 | 2021-03-19 | 2021-03-19 | A |
1500 | 2021-03-20 | 2021-03-22 | A |
2000 | 2021-03-13 | 2021-03-17 | B |
my current sql below but it is not correct at all
SELECT MIN(date) as startDate, MAX(date) as endDate, price, type
FROM prices
GROUP BY type, price
ORDER BY type, MIN(date)
This is a gaps and islands problem, and one simple way to handle it uses the difference in row numbers method. Assuming you are using MySQL 8+, the following should work:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY type ORDER BY date) rn1,
ROW_NUMBER() OVER (PARTITION BY type, price ORDER BY date) rn2
FROM prices
)
SELECT price, MIN(date) AS startDate, MAX(date) AS endDate, type
FROM cte
GROUP BY price, type, rn1 - rn2
ORDER BY type, startDate;
If not using CTE, you can work the following query:
SELECT w1.price, w1.date, w2.date, w1.type FROM
(
SELECT * FROM mytable t1
WHERE NOT EXISTS (
SELECT 1 FROM mytable t2
WHERE
t1.price = t2.price AND
t1.type = t2.type AND
DATEDIFF(t2.date, t1.date) = -1
)
) w1
INNER JOIN
(
SELECT * FROM mytable t1
WHERE NOT EXISTS (
SELECT 1 FROM mytable t2
WHERE
t1.price = t2.price AND
t1.type = t2.type AND
DATEDIFF(t2.date, t1.date) = +1
)
) w2
ON
w1.price = w2.price AND
w1.type = w2.type AND
w1.date <= w2.date AND
NOT EXISTS (
SELECT * FROM mytable t1
WHERE NOT EXISTS (
SELECT 1 FROM mytable t2
WHERE
t1.price = t2.price AND
t1.type = t2.type AND
DATEDIFF(t2.date, t1.date) = +1
)
AND
w1.price = t1.price AND
w1.type = t1.type AND
w1.date <= t1.date AND t1.date < w2.date
)
SELECT MIN(date) as startDate, MAX(date) as endDate, price, type
FROM prices
GROUP BY type, price
ORDER BY MIN(date) ASC
This query might work in arranging data in ascending order of date
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.