我有以下非常大的(~10e8记录)表(table
):
+--------------------------------+ | id order value | +--------------------------------+ | PK int int | | 1 1 1 | | 2 2 5 | | 3 2 | | 4 2 0 | +--------------------------------+
如您所见,value列只能包含非负整数或null。现在,我需要编写一个返回没有value > 0
的订单的查询(即order = 2
不符合条件,因为有value = 5
的记录。
反向查询 很简单:
SELECT order
FROM table
WHERE value > 0
查询的效果对我来说是令人满意的。
但我们不能写完
SELECT order
FROM table
WHERE value = 0
因为可能有一个具有相同顺序的记录,但是value > 0
。我能找到编写该查询的唯一方法是:
SELECT order
FROM table
GROUP BY order
HAVING SUM(COALESCE(value, 0)) = 0
但由于计算了大量数据的总和,查询速度很慢。
有没有办法更有效地编写查询?
答案 0 :(得分:7)
使用exists
:
select o.*
from orders o
where not exists (select 1
from table t
where t.order = o.order and t.value > 0
);
这假设您有一个只包含订单的表(在查询中称为orders
)。此外,它最适合table(order, value)
的索引。
我也想知道以下查询是否具有table(order, value desc)
select t.*
from (select distinct on (order) t.*
from table t
order by order, value desc
) t
where value = 0;
distinct on
应该使用索引进行排序,只需要遇到第一行。然后外部where
将过滤这些,但两次扫描可能会非常快。