चरण 1:हैंडब्रेक छोड़ें
SELECT to_char(MIN(ts)::timestamptz, 'YYYY-MM-DD HH24:MI:SS TZ') AS min_time
,SUM(CASE WHEN sensor_id = 572 THEN value ELSE 0.0 END) AS nickname1
,SUM(CASE WHEN sensor_id = 542 THEN value ELSE 0.0 END) AS nickname2
,SUM(CASE WHEN sensor_id = 571 THEN value ELSE 0.0 END) AS nickname3
FROM sensor_values
-- LEFT JOIN sensor_values_cleaned s2 USING (sensor_id, ts)
WHERE ts >= '2013-10-14T00:00:00+00:00'::timestamptz::timestamp
AND ts < '2013-10-18T00:00:00+00:00'::timestamptz::timestamp
AND sensor_id IN (572, 542, 571, 540, 541, 573)
GROUP BY ts::date AS day
ORDER BY 1;
प्रमुख बिंदु
-
आरक्षित शब्द बदलें (मानक SQL में) आपके पहचानकर्ताओं में।
timestamp
->ts
time
->min_time
-
चूंकि जॉइन समान कॉलम नामों पर होता है, इसलिए आप सरल
USING
खंड शामिल होने की स्थिति में:USING (sensor_id, ts)
हालांकि, दूसरी तालिका के बाद सेsensor_values_cleaned
इस क्वेरी के लिए 100% अप्रासंगिक है, मैंने इसे पूरी तरह से हटा दिया है। -
जैसा कि @joop ने पहले ही सलाह दी है, स्विच करें
min()
औरto_char()
आपके पहले आउट पुट कॉलम में। इस तरह, Postgres मूल स्तंभ मान . से न्यूनतम निर्धारित कर सकते हैं , जो आम तौर पर तेज़ होता है और एक इंडेक्स का उपयोग करने में सक्षम हो सकता है। इस विशिष्ट मामले में,date
के अनुसार आदेश देनाtext
. द्वारा ऑर्डर करने से भी सस्ता है , जिसे मिलान नियमों पर भी विचार करना होगा। -
इसी तरह का विचार आपके
WHERE
. पर भी लागू होता है शर्त:WHERE ts::timestamptz>='2013-10-14T00:00:00+00:00'::timestamptzWHERE ts >= '2013-10-14T00:00:00+00:00'::timestamptz::timestamp
दूसरा है sargable और
ts
. पर एक सादे अनुक्रमणिका का उपयोग कर सकते हैं - बड़ी तालिकाओं में प्रदर्शन पर बहुत प्रभाव के लिए! -
ts::date
. का उपयोग करना के बजायdate_trunc('day', ts)
. सरल, तेज, समान परिणाम। -
संभवत:आपकी दूसरी WHERE स्थिति थोड़ी गलत है। आम तौर पर, आप ऊपरी सीमा को छोड़ देंगे :
स्ट्राइक>AND ts <= '2013-10-18T00:00:00+00:00' ...
AND ts < '2013-10-18T00:00:00+00:00' ...
-
timestamp
मिलाते समय औरtimestamptz
किसी को प्रभावों के बारे में पता होना चाहिए। उदाहरण के लिए, आपकाWHERE
कंडीशन 00:00 स्थानीय समय पर नहीं कटती है (सिवाय इसके कि स्थानीय समय यूटीसी के साथ मेल खाता हो)। विवरण यहाँ:
रेल और पोस्टग्रेएसक्यूएल में टाइमज़ोन को पूरी तरह से नज़रअंदाज़ करना
चरण 2:आपका अनुरोध
और इससे मुझे लगता है कि आपका मतलब है:
... के मान . के बीच का अंतर नवीनतम और शुरुआती टाइमस्टैम्प ...
अन्यथा यह बहुत आसान होगा।
विंडो फ़ंक्शन का उपयोग करें
उसके लिए, विशेष रूप से first_value()
और last_value()
. संयोजन के साथ सावधान, आप एक गैर चाहते हैं -मानक विंडो फ्रेम
इस मामले में last_value() के लिए। तुलना करें:
PostgreSQL एग्रीगेट या विंडो फ़ंक्शन केवल अंतिम मान लौटाने के लिए
मैं इसे <मजबूत>DISTINCT ON
, जो इस मामले में GROUP BY
. की तुलना में अधिक सुविधाजनक है (जिसे एक और सबक्वेरी स्तर की आवश्यकता होगी):
SELECT DISTINCT ON (ts::date, sensor_id)
ts::date AS day
,to_char((min(ts) OVER (PARTITION BY ts::date))::timestamptz
,'YYYY-MM-DD HH24:MI:SS TZ') AS min_time
,sensor_id
,last_value(value) OVER (PARTITION BY ts::date, sensor_id ORDER BY ts
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
- first_value(value) OVER (PARTITION BY ts::date, sensor_id ORDER BY ts)
AS val_range
FROM sensor_values
WHERE ts >= '2013-10-14T00:00:00+0'::timestamptz::timestamp
AND ts < '2013-10-18T00:00:00+0'::timestamptz::timestamp
AND sensor_id IN (540, 541, 542, 571, 572, 573)
ORDER BY ts::date, sensor_id;
चरण 3:पिवट टेबल
उपरोक्त क्वेरी के आधार पर मैं crosstab()
अतिरिक्त मॉड्यूल से tablefunc
:
SELECT * FROM crosstab(
$$SELECT DISTINCT ON (1,3)
ts::date AS day
,to_char((min(ts) OVER (PARTITION BY ts::date))::timestamptz,'YYYY-MM-DD HH24:MI:SS TZ') AS min_time
,sensor_id
,last_value(value) OVER (PARTITION BY ts::date, sensor_id ORDER BY ts RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
- first_value(value) OVER (PARTITION BY ts::date, sensor_id ORDER BY ts) AS val_range
FROM sensor_values
WHERE ts >= '2013-10-14T00:00:00+0'::timestamptz::timestamp
AND ts < '2013-10-18T00:00:00+0'::timestamptz::timestamp
AND sensor_id IN (540, 541, 542, 571, 572, 573)
ORDER BY 1, 3$$
,$$VALUES (540), (541), (542), (571), (572), (573)$$
)
AS ct (day date, min_time text, s540 numeric, s541 numeric, s542 numeric, s571 numeric, s572 numeric, s573 numeric);
रिटर्न (और बहुत पहले से तेज):
day | min_time | s540 | s541 | s542 | s571 | s572 | s573
------------+--------------------------+-------+-------+-------+-------+-------+-------
2013-10-14 | 2013-10-14 03:00:00 CEST | 18.82 | 18.98 | 19.97 | 19.47 | 17.56 | 21.27
2013-10-15 | 2013-10-15 00:15:00 CEST | 22.59 | 24.20 | 22.90 | 21.27 | 22.75 | 22.23
2013-10-16 | 2013-10-16 00:16:00 CEST | 23.74 | 22.52 | 22.23 | 23.22 | 23.03 | 22.98
2013-10-17 | 2013-10-17 00:17:00 CEST | 21.68 | 24.54 | 21.15 | 23.58 | 23.04 | 21.94