Plsql 过滤时查询速度非常慢

Plsql 过滤时查询速度非常慢,plsql,yii2,sql-optimization,Plsql,Yii2,Sql Optimization,我有一个table INVESTOR_OPPORTUNITY,其结构如下: - ID // PRIMARY KEY - INVESTOR_ID - OPPORTUNITY_ID - POINTS // values 0 to 5 一个投资者可以多次与同一个机会关联,每个机会通常有10000名投资者。因此,平均每个opportunity大约有20000行 在我的GridView中,我需要为每个投资者显示一行,其中包含得分为1、2、3、4、5的机会计数。大概是这样的: INVE

我有一个table INVESTOR_OPPORTUNITY,其结构如下:

- ID        // PRIMARY KEY
- INVESTOR_ID
- OPPORTUNITY_ID
- POINTS    // values 0 to 5
一个投资者可以多次与同一个机会关联,每个机会通常有10000名投资者。因此,平均每个opportunity大约有20000行

在我的GridView中,我需要为每个投资者显示一行,其中包含得分为1、2、3、4、5的机会计数。大概是这样的:

INVESTOR_ID    |  count of 1pt  | count of 2pt | etc
123456         |        7       |       13     | etc
以下是查询的主要部分:

        ->select([
            'INVESTOR_ID',
            'SUM( CASE WHEN OPP.POINTS=0 THEN 1 ELSE 0 END) AS countPoints0',
            'SUM( CASE WHEN OPP.POINTS=1 THEN 1 ELSE 0 END) AS countPoints1',
            'SUM( CASE WHEN OPP.POINTS=2 THEN 1 ELSE 0 END) AS countPoints2',
            'SUM( CASE WHEN OPP.POINTS=3 THEN 1 ELSE 0 END) AS countPoints3',
            'SUM( CASE WHEN OPP.POINTS=4 THEN 1 ELSE 0 END) AS countPoints4',
            'SUM( CASE WHEN OPP.POINTS=5 THEN 1 ELSE 0 END) AS countPoints5',
        ])
        ->andWhere([OPPORTUNITY_ID=>$this->OPPORTUNITY_ID])
        ->groupBy(['INVESTOR_ID']);
这往往工作得很好,而且速度相当快。但是,只要我在其中一个计数中筛选出一个值,查询就可能需要17秒以上,有时甚至超过一两分钟

例如:如果我想看到所有拥有1个以上机会且得分为零的投资者:

        ->select([
            'INVESTOR_ID',
            'SUM( CASE WHEN OPP.POINTS=0 THEN 1 ELSE 0 END) AS countPoints0',
            'SUM( CASE WHEN OPP.POINTS=1 THEN 1 ELSE 0 END) AS countPoints1',
            'SUM( CASE WHEN OPP.POINTS=2 THEN 1 ELSE 0 END) AS countPoints2',
            'SUM( CASE WHEN OPP.POINTS=3 THEN 1 ELSE 0 END) AS countPoints3',
            'SUM( CASE WHEN OPP.POINTS=4 THEN 1 ELSE 0 END) AS countPoints4',
            'SUM( CASE WHEN OPP.POINTS=5 THEN 1 ELSE 0 END) AS countPoints5',
        ])
        ->having('SUM( CASE WHEN OPP.POINTS=0 THEN 1 ELSE 0 END) >1')
        ->andWhere([OPPORTUNITY_ID=>$this->OPPORTUNITY_ID])
        ->groupBy(['INVESTOR_ID']);
我尝试了多种指数组合(投资者ID:OPPORTUNITY\ID:POINTS),但运气不佳

如何优化此查询


谢谢你的帮助

首先,在使用having子句进行筛选之前,您有多少行??第二,您正在使用activerecord??显示查询代码的其余部分我不确定,但也许您可以用
和where(['OPP.POINTS'=>0])
替换
having
?结果应该是相同的,但您现在可以使用索引。我想你最好用5列0/1的值来表示点,而不是每次只处理一列。@Bizley不会给出相同的结果,因为如果使用AND,则
OPP.POINTS
中具有不同值的行将在
groupby
之前过滤掉,因此countPoints1-countpoints5将始终为空。但是它可以在子查询中使用,比如
$subquery=…->选择(['INVESTOR\u ID'])->where(['OPP.POINTS'=>0,'OPPORTUNITY\u ID'=>$this->OPPORTUNITY\u ID])
然后在主查询中使用此子查询
->和where(['in','INVESTOR\u ID',$subquery])
而不是使用。这将允许使用索引。@MichalHynčica是的,你说得对。我仍然会选择5列而不是一列。@scaisEdge是的,我正在使用activeRecord。最好的选择是什么?首先,在使用having子句进行筛选之前,您有多少行??第二,您正在使用activerecord??显示查询代码的其余部分我不确定,但也许您可以用
和where(['OPP.POINTS'=>0])
替换
having
?结果应该是相同的,但您现在可以使用索引。我想你最好用5列0/1的值来表示点,而不是每次只处理一列。@Bizley不会给出相同的结果,因为如果使用AND,则
OPP.POINTS
中具有不同值的行将在
groupby
之前过滤掉,因此countPoints1-countpoints5将始终为空。但是它可以在子查询中使用,比如
$subquery=…->选择(['INVESTOR\u ID'])->where(['OPP.POINTS'=>0,'OPPORTUNITY\u ID'=>$this->OPPORTUNITY\u ID])
然后在主查询中使用此子查询
->和where(['in','INVESTOR\u ID',$subquery])
而不是使用。这将允许使用索引。@MichalHynčica是的,你说得对。我仍然会选择5列而不是一列。@scaisEdge是的,我正在使用activeRecord。最好的选择是什么?