PostgreSQL 9.4에 다음과 같은 테이블이 있습니다.
CREATE TABLE dates_ranges (kind int, start_date date, end_date date);
INSERT INTO dates_ranges VALUES
(1, '2018-01-01', '2018-01-31'),
(1, '2018-01-01', '2018-01-05'),
(1, '2018-01-03', '2018-01-06'),
(2, '2018-01-01', '2018-01-01'),
(2, '2018-01-01', '2018-01-02'),
(3, '2018-01-02', '2018-01-08'),
(3, '2018-01-05', '2018-01-10');
이제 주어진 날짜와 모든 종류에 dates_ranges
대해 각 날짜의 행 수를 계산하려고합니다 . 0은 생략 될 수 있습니다.
원하는 결과 :
+-------+------------+----+
| kind | as_of_date | n |
+-------+------------+----+
| 1 | 2018-01-01 | 2 |
| 1 | 2018-01-02 | 2 |
| 1 | 2018-01-03 | 3 |
| 2 | 2018-01-01 | 2 |
| 2 | 2018-01-02 | 1 |
| 3 | 2018-01-02 | 1 |
| 3 | 2018-01-03 | 1 |
+-------+------------+----+
나는 두 가지 솔루션, 하나 마련했습니다 LEFT JOIN
및GROUP BY
SELECT
kind, as_of_date, COUNT(*) n
FROM
(SELECT d::date AS as_of_date FROM generate_series('2018-01-01'::timestamp, '2018-01-03'::timestamp, '1 day') d) dates
LEFT JOIN
dates_ranges ON dates.as_of_date BETWEEN start_date AND end_date
GROUP BY 1,2 ORDER BY 1,2
와 하나 LATERAL
는 약간 빠릅니다.
SELECT
kind, as_of_date, n
FROM
(SELECT d::date AS as_of_date FROM generate_series('2018-01-01'::timestamp, '2018-01-03'::timestamp, '1 day') d) dates,
LATERAL
(SELECT kind, COUNT(*) AS n FROM dates_ranges WHERE dates.as_of_date BETWEEN start_date AND end_date GROUP BY kind) ss
ORDER BY kind, as_of_date
이 쿼리를 작성하는 것이 더 좋은 방법인지 궁금합니다. 그리고 0 카운트와 날짜 종류 쌍을 포함시키는 방법은 무엇입니까?
실제로 몇 가지 종류, 최대 5 년 (1800 일), ~ 30k 개의 행이 있습니다 dates_ranges
(그러나 크게 늘어날 수 있음).
인덱스가 없습니다. 내 경우에는 정확하게는 하위 쿼리의 결과이지만 질문을 하나의 문제로 제한하고 싶기 때문에 더 일반적입니다.
2018-01-31
또는 2018-01-30
또는 2018-01-29
최초의 범위는 그들 모두를 가질 때 거기에?
generate_series
는 외부 매개 변수이므로 반드시 dates_ranges
표의 모든 범위를 다룰 필요는 없습니다 . 첫 번째 질문에 대해서는 이해하지 못한다고 가정합니다. 행 dates_ranges
은 독립적이므로 중복을 결정하고 싶지 않습니다.
(1,2018-01-01,2018-01-15)
그리고(1,2018-01-20,2018-01-25)
당신은 얼마나 많은 중복 날짜를 결정할 때 당신이 고려하는 것이 먹고 싶어합니까?