2012-06-29 31 views
6

मेरे पास हर मिनट सभी डेटा गिनने के लिए निम्न क्वेरी है।तालिका के प्रत्येक 3 पंक्तियों को

$sql= "SELECT COUNT(*) AS count, date_trunc('minute', date) AS momento 
FROM p WHERE fk_id_b=$id_b GROUP BY date_trunc('minute', date) 
ORDER BY momento ASC"; 

मुझे क्या करना है कि प्रत्येक पंक्ति के लिए 2 पिछले मिनट की गिनती के साथ गिनती का योग प्राप्त करें।

For example with the result of the $sql query above 
|-------date---------|----count----| 
|2012-06-21 05:20:00 |  12  | 
|2012-06-21 05:21:00 |  14  | 
|2012-06-21 05:22:00 |  10  | 
|2012-06-21 05:23:00 |  20  | 
|2012-06-21 05:24:00 |  25  | 
|2012-06-21 05:25:00 |  30  | 
|2012-06-21 05:26:00 |  10  | 

I want this result: 

|-------date---------|----count----| 
|2012-06-21 05:20:00 |  12  | 
|2012-06-21 05:21:00 |  26  |  12+14 
|2012-06-21 05:22:00 |  36  |  12+14+10 
|2012-06-21 05:23:00 |  44  |  14+10+20 
|2012-06-21 05:24:00 |  55  |  10+20+25 
|2012-06-21 05:25:00 |  75  |  20+25+30 
|2012-06-21 05:26:00 |  65  |  25+30+10 
+0

बहुत एसक्यूएल के साथ मुश्किल में इस पर अधिक जानकारी प्राप्त कर सकते हैं। क्या आपका आवेदन काम नहीं कर सकता? आपको पंक्तियों को वैसे भी लाया जाना है, और आप उसी लूप में ऐसा कर सकते हैं। – Searle

+0

@ पार्थ भट्ट: आपके द्वारा अनुमोदित संपादन स्पष्ट रूप से एक अलग प्रश्न पूछ रहा है। कृपया इस तरह के संपादन को स्वीकार न करें। – interjay

+0

@interjay: मेरी गलती क्षमा करें, मैंने इसे गलत तरीके से व्याख्या की। –

उत्तर

10

यह lag() window function (भी SQL Fiddle पर) के साथ इतना मुश्किल नहीं है:

CREATE TABLE t ("date" timestamptz, "count" int4); 
INSERT INTO t VALUES 
('2012-06-21 05:20:00',12), 
('2012-06-21 05:21:00',14), 
('2012-06-21 05:22:00',10), 
('2012-06-21 05:23:00',20), 
('2012-06-21 05:24:00',25), 
('2012-06-21 05:25:00',30), 
('2012-06-21 05:26:00',10); 

SELECT *, 
    "count" 
    + coalesce(lag("count", 1) OVER (ORDER BY "date"), 0) 
    + coalesce(lag("count", 2) OVER (ORDER BY "date"), 0) AS "total" 
    FROM t; 
  1. मैं, डबल-कोटेड date और count कॉलम है के रूप में इन आरक्षित शब्द हैं;
  2. lag(field, distance) मुझे field कॉलम distance पंक्तियों को वर्तमान में से दूर करता है, इस प्रकार पहला फ़ंक्शन पिछली पंक्ति का मान देता है और दूसरा कॉल पहले से मान देता है;
  3. coalesce()lag() समारोह से NULL परिणाम से बचने के लिए आवश्यक है (अपने प्रश्न में पहली पंक्ति के लिए कोई "पिछले" एक प्रकार यह NULL है,), अन्यथा total भी NULL हो जाएगा।
+0

बढ़िया! मुझे खिड़की के कार्यों की अवधारणा पसंद है लेकिन उनका उपयोग करना भूल जाते हैं। सही समाधान के लिए एक upvote है :-) – Searle

+0

+1। मैंने एक जवाब लिखा, क्योंकि टिप्पणी पर्याप्त नहीं है। –

9

@vyegorov's answer इसे अधिकतर कवर करता है। लेकिन मेरे पास एक टिप्पणी में फिट होने की तुलना में अधिक पकड़ है।

  1. सभी पर reserved words पहचानकर्ता के रूप में date की तरह और countप्रयोग न करें। PostgreSQL उन दो विशेष कुंजी शब्दों को पहचानकर्ता के रूप में अनुमति देता है - प्रत्येक SQL मानक के अलावा। लेकिन यह अभी भी बुरा अभ्यास है। तथ्य यह है कि आप पहचानकर्ता के रूप में डबल-कोट्स के अंदर कुछ भी उपयोग कर सकते हैं, यहां तक ​​कि "; DELETE FROM tbl;" यह एक अच्छा विचार नहीं बनाता है। के लिए "date" नाम उस पर सबसे ऊपर भ्रामक है।

  2. गलत डेटा प्रकार। उदाहरण timestamp प्रदर्शित करता है, timestamptz नहीं। यहां कोई फर्क नहीं पड़ता है, लेकिन अभी भी भ्रामक है।

  3. आपको COALESCE() की आवश्यकता नहीं है। इस स्थापना पर

बिल्डिंग: window functions lag() and lead() के साथ आप 3 पैरामीटर के रूप में एक डिफ़ॉल्ट मान प्रदान कर सकते हैं कर सकते हैं

CREATE TABLE tbl (ts timestamp, ct int4); 
INSERT INTO tbl VALUES 
    ('2012-06-21 05:20:00', 12) 
, ('2012-06-21 05:21:00', 14) 
, ('2012-06-21 05:22:00', 10) 
, ('2012-06-21 05:23:00', 20) 
, ('2012-06-21 05:24:00', 25) 
, ('2012-06-21 05:25:00', 30) 
, ('2012-06-21 05:26:00', 10); 

क्वेरी:

SELECT ts, ct + lag(ct, 1, 0) OVER (ORDER BY ts) 
       + lag(ct, 2, 0) OVER (ORDER BY ts) AS total 
FROM tbl; 

या बेहतर अभी तक : खिड़की के कुल समारोह के रूप में एक sum() का उपयोग करें वें custom window frame:

SELECT ts, sum(ct) OVER (ORDER BY ts ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) 
FROM tbl; 

वही परिणाम।
संबंधित:

+0

'lag' /' lead' के लिए डिफ़ॉल्ट मान एक अच्छा है! – vyegorov

10

यहाँ वर्तमान और से मानों का योग के लिए एक अधिक सामान्य समाधान है एन पिछले पंक्तियों (एन = अपने मामले में 2)।

SELECT "date", 
sum("count") OVER (order by "date" ROWS BETWEEN 2 preceding AND current row) 
FROM t 
ORDER BY "date"; 

आप 0 और "Unbounded" के बीच एन को बदल सकते हैं। यह दृष्टिकोण आपको अपने ऐप "एन पिछले मिनटों की गिनती" में पैरामीटर रखने का मौका देता है। इसके अलावा, सीमाओं से बाहर होने पर डिफ़ॉल्ट मानों को संभालने की कोई आवश्यकता नहीं है।

आप PostgreSQL डॉक्स (4.2.8. Window Function Calls)

+0

स्वीकार्य उत्तर से यह एक बेहतर समाधान है – user2259664