有两个表A和B,其中包含以下列和示例数据
表 A
Id Code Name Active
---------------------------------
1 A1 Apple t
2 B2 Banana t
3 C1 Cherry f
4 D2 Date t
表 B
Aid Received
-----------------------------------
1 2014-10-02 10:24:55.095714
2 2014-10-02 10:54:53.226128
3 2014-10-02 15:39:59.683531
1 2014-10-02 15:39:59.862021
4 2014-10-02 15:42:19.923144
4 2014-10-02 15:49:29.964731
1 2014-10-02 15:53:27.586373
Aid
是表 A
我需要显示最后一小时收到的所有姓名,号码和最后收到的时间
样本数据的预期输出如下
Name Count LastReceived
-------------------------------------------
Banana 0 2014-10-02 10:54:53.226128
Apple 2 2014-10-02 15:53:27.586373
Date 1 2014-10-02 15:49:29.964731
到目前为止我写的查询如下
SELECT
A.name,
COUNT(B.Aid) AS Count,
MAX(B.Received) AS LastReceived
FROM
A
FULL OUTER JOIN
B
ON A.id = B.Aid
WHERE B.Received > (NOW() - INTERVAL '1 hour') AND A.Active = TRUE --approx. 3pm to 4pm 10/2/2014
GROUP BY A.name
ORDER BY Count, A.name
我没有通过此查询获得预期的输出。我应该如何修改查询以获得预期的输出?
编辑
我需要将结果排序为零,计数首先按字母顺序显示,然后按字母顺序显示。我可以在一个查询中执行此操作吗?我知道添加ORDER BY Count, A.name
将无效。
答案 0 :(得分:3)
您遇到的麻烦是where子句排除了您要为上次收到的日期考虑的行。解决这个问题的一种方法是使用条件聚合:
select
a.name,
sum(case when b.Received > (now() - interval '1 hour') then 1 else 0 end) AS Count,
max(b.Received) as LastReceived
from
a
left outer join
b
on a.id = b.aid
where
a.Active = true
group by
a.name
order by
case when sum(case when b.Received > (now() - interval '1 hour') then 1 else 0 end) = 0 then 0 else 1 end,
a.name
通过拉出公用表表达式,可以更容易理解按工作顺序的方式:
with x as (
select
a.name,
sum(case when b.Received > '2014-10-02 15:00:00' then 1 else 0 end) AS Count,
max(b.Received) as LastReceived
from
a
left outer join
b
on a.id = b.aid
where
a.Active = true
group by
a.name
) select
x.name,
x.count,
x.lastreceived
from
x
order by
case when x.Count = 0 then 0 else 1 end,
x.name
答案 1 :(得分:0)
您的查询几乎正确,但您需要LEFT JOIN
,因为表A
是您的驾驶关系:
SELECT a.name,
count(b.aid),
max(b.received) AS LastReceived
FROM a
LEFT JOIN b ON a.id=b.aid AND b.received > now()-INTERVAL '1 hour'
WHERE a.active
GROUP BY a.name
ORDER BY a.name;
此外,重要的是,您是否过滤掉WHERE
子句中的结果,在您的情况下,跳过所有可能产生零计数的条目,或者将过滤器置于连接条件中(如上所述。)