PostgreSQL - 如何从同一个表中获取空(空)记录?

时间:2013-12-11 13:26:11

标签: postgresql

我想从我的表中获取数据,包括空行。例如:我想知道,如果在过去的30分钟内有一些活动。如果有什么东西,那么我可以获取数据并且它可以工作,但是如何在没有任何活动的情况下包含这些记录?我的所有数据都在同一张表中。

谢谢!

    ╔═════╦═════════════════════╦══════╗
    ║ 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

2 个答案:

答案 0 :(得分: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,那么用NULL替换0:

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

但是这个查询将始终读取整个表格,因此可能是无效的
以下版本读取所有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

答案 1 :(得分:0)

我会非常简单地做到这一点 - 首先,我会使用一些具有srv的所有可能值的表(我使用数组,以保持简单)然后只计算{{1的所有标志值:

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替换为 这张桌子的名字。