programing

날짜 범위에서 매일 행을 생성하시겠습니까?

projobs 2022. 9. 29. 22:13
반응형

날짜 범위에서 매일 행을 생성하시겠습니까?

제 테이블은 다음과 같습니다.

+----+---------+------------+
| id |  price  |    date    |
+----+---------+------------+
| 1  | 340     | 2018-09-02 |
| 2  | 325     | 2018-09-05 |
| 3  | 358     | 2018-09-08 |
+----+---------+------------+

그리고 나는 매일 일렬로 서있는 뷰를 만들어야 한다.다음과 같은 경우:

+----+---------+------------+
| id |  price  |    date    |
+----+---------+------------+
| 1  | 340     | 2018-09-02 |
| 1  | 340     | 2018-09-03 |
| 1  | 340     | 2018-09-04 |
| 2  | 325     | 2018-09-05 |
| 2  | 325     | 2018-09-06 |
| 2  | 325     | 2018-09-07 |
| 3  | 358     | 2018-09-08 |
+----+---------+------------+

루프가 있는 PHP를 사용하여 할 수 있습니다.foreach새로운 날짜가 있을 때까지 이전 가격을 유지하는 Temp 변수를 만듭니다.

하지만 난 견해를 밝혀야 해그럼 Pure-SQL을 사용해서...어떻게 하면 좋을까요?

재귀 CTE를 사용하여 "갭"에 레코드를 생성할 수 있습니다.마지막 날짜 이후의 무한 공백이 "채워지지 않도록" 하려면 먼저 소스 데이터에서 최대 날짜를 가져오고 재귀에서 해당 날짜를 무시하지 않도록 하십시오.

테이블을 불렀습니다tbl:

with recursive cte as (
    select     id, 
               price, 
               date, 
               (select max(date) date from tbl) mx
    from       tbl
    union all
    select     cte.id,
               cte.price, 
               date_add(cte.date, interval 1 day),
               cte.mx
    from       cte
    left join  tbl
           on  tbl.date = date_add(cte.date, interval 1 day)
    where      tbl.id is null
           and cte.date <> cte.mx
)
select   id, 
         price, 
         date
from     cte
order by 3;

mysql 8을 사용한 데모

여기 분석 기능 없이 작동해야 하는 접근법이 있습니다.이 답변에서는 캘린더 테이블 조인 방식을 사용합니다.다음 첫 번째 CTE는 나머지 쿼리의 기반이 되는 기본 테이블입니다.관련된 서브쿼리를 사용하여 CTE의 현재 날짜보다 이전 최신 날짜를 찾습니다.NULL가격입니다. 이것은 이 모든 것을 알아내기 위한 기초가 됩니다.id그리고.price값은 원래 데이터 세트에 나타나지 않는 달력 테이블에서 들어오는 날짜에 대한 값이어야 합니다.

WITH cte AS (    
    SELECT cal.date, t.price, t.id
    FROM
    (
        SELECT '2018-09-02' AS date UNION ALL
        SELECT '2018-09-03' UNION ALL
        SELECT '2018-09-04' UNION ALL
        SELECT '2018-09-05' UNION ALL
        SELECT '2018-09-06' UNION ALL
        SELECT '2018-09-07' UNION ALL
        SELECT '2018-09-08'
    ) cal
    LEFT JOIN yourTable t
        ON cal.date = t.date
),
cte2 AS (
    SELECT
        t1.date,
        t1.price,
        t1.id,
        (SELECT MAX(t2.date) FROM cte t2
         WHERE t2.date <= t1.date AND t2.price IS NOT NULL) AS nearest_date
    FROM cte t1
)

SELECT
    (SELECT t2.id FROM yourTable t2 WHERE t2.date = t1.nearest_date) id,
    (SELECT t2.price FROM yourTable t2 WHERE t2.date = t1.nearest_date) price,
    t1.date
FROM cte2 t1
ORDER BY
    t1.date;

여기에 이미지 설명 입력

데모

주의: 이 기능을 8+보다 이전 버전의 MySQL에서 사용하려면 위의 CTE를 인라인해야 합니다.자세한 코드가 표시되지만 여전히 작동해야 합니다.

MariaDB 를 사용하고 있기 때문에, 다음의 조작은 매우 간단합니다.

MariaDB [test]> SELECT  '2019-01-01' + INTERVAL seq-1 DAY  FROM seq_1_to_31;
+-----------------------------------+
| '2019-01-01' + INTERVAL seq-1 DAY |
+-----------------------------------+
| 2019-01-01                        |
| 2019-01-02                        |
| 2019-01-03                        |
| 2019-01-04                        |
| 2019-01-05                        |
| 2019-01-06                        |
(etc)

다양한 날짜를 생성하지만 WHERE를 사용하여 원하는 대로 잘라내는 등 다양한 종류가 있습니다.그리고 사용LEFT JOIN'왼쪽'에 '파생표' 시퀀스가 표시됩니다.

쿼리의 파생 테이블로 위와 같은 것을 사용합니다.

언급URL : https://stackoverflow.com/questions/54651471/create-a-row-for-every-day-in-a-date-range

반응형