1

Let's say I have 2 tables: table device is a set of measuring devices, table data is a set of values of different types measured by the devices.

Table data = (no, id,value_type,value, dayhour) no is PK, id refer to table device
Table device = (id, name) id is PK

I currently have a query that will obtain the sum of all values of a specific value_type generated by an id on a specific date, something like:

SELECT SUM(cast(a.value as int)),b.name FROM data a INNER JOIN device b
ON a.id=b.id 
AND a.id=1
AND a.value_type=2
AND date(a.dayhour)='2015-12-12'
GROUP BY b.name

The query works without problems. Now I want to be able to subtract the sum of different value types. What I'm currently doing is two queries, one for obtaining the sum for value_type 2 and another for the sum for value_type 3 and then doing the subtraction at an upper layer process.

However, I would like to do this from a single query, something like a query that will retrieve one column with the sum of value_type 2, another with the sum of value_type 3 and a third one with the subtraction of these 2 columns.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
user3851205
  • 75
  • 1
  • 8
  • Please provide proper table definitions: what you get with `\d tbl` in psql or original `CREATE TABLE` scripts. Also, as *always*: your version of Postgres. – Erwin Brandstetter Feb 10 '15 at 02:42

1 Answers1

2
SELECT b.name, a.*, a.sum2 - a.sum3 AS diff
FROM  (
    SELECT id
         , sum(CASE WHEN value_type = 2 THEN value::int END) AS sum2
         , sum(CASE WHEN value_type = 3 THEN value::int END) AS sum3
    FROM   data
    WHERE  id = 1
    AND    value_type IN (2, 3)
    AND    dayhour >= '2015-12-12 0:0'::timestamp
    AND    dayhour <  '2015-12-13 0:0'::timestamp
    GROUP  BY 1
    ) a
JOIN   device b USING (id);
  • Assuming dayhour is of data type timestamp (information is missing). The cast to date would disable basic indexes. That's why I transformed it to a sargable predicate. More details:
  • Why the cast value::int?
  • Aggregate first, then join to device. Cheaper.
Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Thanks!!!! This is exactly what I needed. I've been playing with CASE statement but didn't find the correct syntax – user3851205 Feb 10 '15 at 03:22