मेरे पास एक टेबल है (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)
क्या आप यह निर्धारित करना चाहते हैं कि आपके पास कितनी ओवरलैपिंग तिथियां हैं?