* How to Display Dates Easily in SQL?
We have a database table TBLDATES as follows:
DATES |
2020-08-08 |
2020-08-10 |
2020-08-11 |
2020-08-12 |
2020-08-16 |
2020-09-20 |
2020-09-27 |
2020-09-28 |
2020-09-29 |
2020-09-30 |
2020-10-01 |
2020-10-02 |
We are trying to group the dates by year and month, and in each group, separate continuous dates with the hyphen and the discontinuous dates with the comma. Below is the desired result:
year |
month |
days |
2020 |
8 |
8,10-12,16 |
2020 |
9 |
20,27-30 |
2020 |
10 |
1-2 |
The result table is ordered by dates which are grouped by year and month. Continuous dates are connected by the hyphen (-) and discontinuous ones are connected by the comma.
SQL in MySQL:
with_counter AS (
SELECT
*
, CASE WHEN LAG(DATES) OVER(PARTITION BY MONTH(DATES) ORDER BY DATES) + 1 < DATES
OR LAG(DATES) OVER(PARTITION BY MONTH(DATES) ORDER BY DATES) IS NULL
THEN 1
ELSE 0
END AS counter
FROM TBLDATES
)
,
with_session AS (
SELECT
*
, SUM(counter) OVER(ORDER BY MONTH(DATES), DAY(DATES)) AS session
FROM with_counter
)
SELECT
CAST(MIN(DAY(DATES)) AS VARCHAR(2)) ||CASE WHEN COUNT(*) = 1
THEN ''
ELSE '-'||CAST(MAX(DAY(DATES)) AS VARCHAR(2))
END
AS daylit
, DAY(MIN(DATES)) AS d
, MONTH(MIN(DATES)) AS mn
, TO_CHAR(MIN(DATES),'Month') AS mth
, YEAR(MIN(DATES)) AS yr
FROM with_session
GROUP BY session
ORDER BY 3,2;
The task is not difficult. We can first group dates by year and month and then dates in each month by whether they are continuous or not (a date is continuous if the result of subtracting the previous date from it is 1, otherwise it isn’t). The dates in August, for instance, can be divided into three groups. The first group contains 8, the second contains 10, 11 and 12, and the third contains 16. Then we find the subgroup containing more than one number (which is the second group for August), join numbers with the hyphen (-), and connect members in the group by comma. The problem is that SQL can only perform equi-grouping by a specific column and that does not support grouping by continuous conditions. The language’s solution is rather tricky by inventing a specific column and performing grouping by it.
It is easy and simple to do it with the open-source esProc SPL:
A |
|
1 |
=connect("MYSQL") |
2 |
=A1.query@xi("SELECT * FROM TBLDATES ORDER BY DATES") |
3 |
=A2.group(year(~):year,month(~):month;~.(day(~)).group@i(~-~[-1]!=1).(if(~.len()>1,~.m(1)/"-"/~.m(-1),~.m(1))).concat@c():days) |
SPL supports grouping by the continuous conditions. It is convenient to perform such a grouping operation (like this task) with SPL.
https://stackoverflow.com/questions/64116840/sql-formatting-to-user-friendly-date
SPL Official Website 👉 https://www.scudata.com
SPL Feedback and Help 👉 https://www.reddit.com/r/esProcSPL
SPL Learning Material 👉 https://c.scudata.com
SPL Source Code and Package 👉 https://github.com/SPLWare/esProc
Discord 👉 https://discord.gg/cFTcUNs7
Youtube 👉 https://www.youtube.com/@esProc_SPL