ฉันมีตาราง (ใน 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
แต่ละวันที่ตก อาจตัดศูนย์ได้
ผลลัพธ์ที่ต้องการ:
+-------+------------+----+
| 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?
ในความเป็นจริงมีไม่กี่ชนิดที่แตกต่างกันระยะเวลาถึงห้าปี (วันที่ 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)
คุณต้องการคำนึงถึงเรื่องนี้เมื่อพิจารณาว่าคุณมีวันที่ทับซ้อนกันจำนวนเท่าใด