2013-12-11 3 views
1

Я хотел бы получить данные из моей таблицы, включая пустые строки. Например: я хочу знать, была ли какая-то активность за последние 30 минут. Если что-то есть, то я могу получить данные, и это работает, но как включить эти записи без какой-либо активности? Все мои данные находятся в одной таблице.PostgreSQL - Как получить пустые (нулевые) записи из одной таблицы?

Спасибо!

╔═════╦═════════════════════╦══════╗ 
    ║ SRV ║  DATE   ║ FLAG ║ 
    ╠═════╬═════════════════════╬══════╣ 
    ║ 1 ║ 2013-01-01 08:10:12 ║ 4 ║ 
    ║ 1 ║ 2013-01-01 08:11:24 ║ 4 ║ 
    ║ 1 ║ 2013-01-01 08:12:01 ║ 5 ║ 
    ║ 1 ║ 2013-01-01 08:12:14 ║ 5 ║ 
    ║ 2 ║ 2013-01-01 08:20:44 ║ 4 ║ 
    ║ 2 ║ 2013-01-01 08:23:11 ║ 5 ║ 
    ║ 1 ║ 2013-01-01 08:24:09 ║ 4 ║ 
    ║ 1 ║ 2013-01-01 08:28:54 ║ 5 ║ 
    ║ 1 ║ 2013-01-01 08:30:01 ║ 4 ║ 
    ║ 3 ║ 2013-01-01 08:32:31 ║ 4 ║ 
    ║ 3 ║ 2013-01-01 08:32:45 ║ 4 ║ 
    ║ 1 ║ 2013-01-01 08:35:21 ║ 4 ║ 
    ╚═════╩═════════════════════╩══════╝ 

Я хочу получить количество флагов со статусом 4, за последние 10 минут в этом случае, сгруппированные по SRV. Если в указанный период не было флага 4, должна быть запись с SRV и значением NULL. В этом случае мой запрос должен возвращать:

╔═════╦═══════╦══╗ 
║ SRV ║ COUNT ║ ║ 
╠═════╬═══════╬══╣ 
║ 1 ║ 2  ║ ║ 
║ 2 ║ NULL ║ ║ 
║ 3 ║ 2  ║ ║ 
╚═════╩═══════╩══╝ 

Я был в состоянии сосчитать существующие флаги с помощью:

select srv, count(*) 
from table1 
where flag=4 and date >= now() - interval '10m' 
group by svr 
order by 1 
+3

Можете ли вы показать структуру вашей таблицы, пример данных и результата, а также запросы, которые вы уже пытались написать? –

ответ

0

Попробуйте с SUM, это вернет 0

select srv, SUM(CASE WHEN flag=4 THEN 1 ELSE 0 END) 
from table1 
where date >= now() - interval '10m' 
group by svr 
order by 1 

Если вы действительно требуется NULL, затем заменить 0 на NULL:

select srv, 
     CASE SUM(CASE WHEN flag=4 THEN 1 ELSE 0 END) 
      WHEN 0 THEN NULL 
      ELSE SUM(CASE WHEN flag=4 THEN 1 ELSE 0 END) 
     END 
from table1 
where date >= now() - interval '10m'now() - interval '10m' 
group by svr 
order by 1 

Если в течение последних 30 минут нет записей с некоторым значением SRV, то указанные выше запросы не отображают этот SRV.
Чтобы исправить это, вы можете использовать этот запрос:

select srv, 
     SUM(CASE WHEN flag=4 AND date >= (now() - interval '10m') 
      THEN 1 ELSE 0 END) 
from table1 
group by srv 
order by 1 

, но этот запрос всегда будет читать всю таблицу, поэтому может быть ineficcient.

В приведенной ниже версии считываются все значения SRV (если в столбце SRV есть индекс, эта операция должна быть быстрой) и выполнять агрегацию только в подмножестве таблицы (последние 30 минут), поэтому может быть быстрее, чем предыдущий:

SELECT q1.srv, q2.cnt 
FROM (
    SELECT DISTINCT srv 
    FROM table1 
) q1 
LEFT JOIN (
    select srv, count(*) as cnt 
    from table1 
    where flag=4 AND date >= now() - interval '10m' 
    group by svr 
) q2 
ON q1.srv = q2.srv 
+0

К сожалению, это не работает :(Я получаю тот же результат, что и для использования count (*). –

+0

@ user3091257 Прошу прощения, были ошибки в запросах. Я исправил их и добавил несколько новых запросов. – krokodilko

+0

Спасибо! Это то, чего я должен был достичь :) Работает блестяще. Я думал об использовании «join», но я новичок в SQL. Я могу понять, как присоединиться к двум различным таблицам, но я не знал, что вы можете присоединить таблицу к себе. Кроме того, внешнее соединение - это то, что мне нужно узнать, потому что для меня это немного сложно (на данный момент). –

0

Я хотел бы сделать это на самом деле просто - во-первых, я хотел бы использовать некоторую таблицу со всеми возможными значениями srv (я использовал массив для того, чтобы сохранить его простым), а затем просто подсчитать все флаги для что srv значение:

SELECT 
    s.x, CASE WHEN s.num = 0 THEN NULL ELSE s.num END 
FROM (
    SELECT x, (
     SELECT COUNT(1) 
     FROM table1 
     WHERE flag = 4 AND date >= NOW() - INTERVAL '10m' AND srv = x 
    ) AS num 
    FROM 
     UNNEST(ARRAY[1, 2, 3]) AS x 
    ORDER by x) AS s; 

Это возвращает:

x | num 
---+----- 
1 | 2 
2 |  
3 | 2 
(3 rows) 

Если у вас есть srv значения в некоторой таблице, просто замените UNNEST(ARRAY[..]) с имя этой таблицы.

Смежные вопросы