Отложить два запроса из одной таблицы

Допустим, у меня есть 2 таблицы: таблица device — набор измерительных приборов, таблица data — набор значений разных типов, измеряемых приборами.

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

В настоящее время у меня есть запрос, который будет получать сумму всех значений определенного value_type, сгенерированного id в определенную дату, например:

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

Запрос работает без проблем. Теперь я хочу иметь возможность вычитать сумму различных типов значений. В настоящее время я делаю два запроса: один для получения суммы для value_type 2, а другой для суммы для value_type 3, а затем выполняю вычитание в процессе верхнего уровня.

Однако я хотел бы сделать это из одного запроса, что-то вроде запроса, который будет извлекать один столбец с суммой value_type 2, другой с суммой value_type 3 и третий с вычитанием этих 2 столбцов.


person user3851205    schedule 10.02.2015    source источник
comment
Пожалуйста, предоставьте правильные определения таблиц: что вы получаете с \d tbl в psql или оригинальными CREATE TABLE скриптами. Кроме того, как всегда: ваша версия Postgres.   -  person Erwin Brandstetter    schedule 10.02.2015


Ответы (1)


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:
  • Почему актерский состав value::int?
  • Сначала агрегируйте, а затем присоединяйтесь к устройству. Дешевле.
person Erwin Brandstetter    schedule 10.02.2015
comment
Спасибо!!!! Это именно то, что мне нужно. Я играл с оператором CASE, но не нашел правильного синтаксиса - person user3851205; 10.02.2015