postgres CASE和where子句

时间:2018-04-12 10:56:51

标签: postgresql

假设我有一个像这样的表:

Select count(case when type=1 and status='A' and date<'2018-04-01' then id) as type1, 
count(case when type=2 and status='A' and date<'2018-04-01' then id)as type2
FROM table

现在查询1:

Select count(case when type=1 then id) as type1, 
    count(case when type=2 then id)as type2 
FROM table where status='A' and date < '2018-04-01' 

AND查询2:

private static Matcher<View> withAdaptedData(final Matcher<Object> dataMatcher) {
return new TypeSafeMatcher<View>() {

    @Override
    public void describeTo(Description description) {
        description.appendText("with class name: ");
        dataMatcher.describeTo(description);
    }

    @Override
    public boolean matchesSafely(View view) {
        if (!(view instanceof AdapterView)) {
            return false;
        }

        @SuppressWarnings("rawtypes")
        Adapter adapter = ((AdapterView) view).getAdapter();
        for (int i = 0; i < adapter.getCount(); i++) {
            if (dataMatcher.matches(adapter.getItem(i))) {
                return true;
            }
        }

        return false;
    }
};
}

这些都是相同的,如果是的话,那就更好了

2 个答案:

答案 0 :(得分:1)

如果您在date列上有索引,那么第二个版本可能会比第一个版本执行得更好。这样做的原因是,即使必须在WHERE子句中进行条件聚合,Postgres也能够过滤掉SELECT中的许多记录。

如果date没有索引,那么在任何一种情况下,Postgres都必须触及表中的每条记录。

答案 1 :(得分:0)

使用这样的架构:

create table tbl
(
    id     int primary key,
    item   text,
    type   int,
    status text, 
    date   date
);

insert into tbl values
(1, 'A', 1, 'P', '2018-04-01'),
(2, 'B', 2, 'A', '2018-01-01'),
(3, 'C', 1, 'A', '2018-01-02'),
(4, 'D', 2, 'A', '2018-04-11');

第二个查询执行得更好,因为:

Rows Removed by Filter: 2

但他们都没有使用任何索引,因为你需要考虑大量数据来添加新索引并再次检查性能。

explain (analyze,buffers)
select count(case when type = 1 and status = 'A' and date < '2018-04-01' then id end) as type1, 
       count(case when type = 2 and status = 'A' and date < '2018-04-01' then id end) as type2
from   tbl;
| QUERY PLAN                                                                                            |
| :---------------------------------------------------------------------------------------------------- |
| Aggregate  (cost=33.40..33.41 rows=1 width=16) (actual time=0.022..0.022 rows=1 loops=1)              |
|   Buffers: shared hit=1                                                                               |
|   ->  Seq Scan on tbl  (cost=0.00..17.80 rows=780 width=44) (actual time=0.006..0.007 rows=4 loops=1) |
|         Buffers: shared hit=1                                                                         |
| Planning time: 0.171 ms                                                                               |
| Execution time: 0.121 ms                                                                              |
explain (analyze,buffers)
select count(case when type=1 then id end) as type1, 
       count(case when type=2 then id end)as type2 
from   tbl 
where  status = 'A' 
and    date < '2018-04-01';
| QUERY PLAN                                                                                         |
| :------------------------------------------------------------------------------------------------- |
| Aggregate  (cost=21.71..21.72 rows=1 width=16) (actual time=0.007..0.008 rows=1 loops=1)           |
|   Buffers: shared hit=1                                                                            |
|   ->  Seq Scan on tbl  (cost=0.00..21.70 rows=1 width=8) (actual time=0.004..0.005 rows=2 loops=1) |
|         Filter: ((date < '2018-04-01'::date) AND (status = 'A'::text))                             |
|         Rows Removed by Filter: 2                                                                  |
|         Buffers: shared hit=1                                                                      |
| Planning time: 0.084 ms                                                                            |
| Execution time: 0.032 ms                                                                           |

dbfiddle here