2

这有点难,因为我对 Postgresql 的 pgsql 或 C 了解不多。

我希望有人可以通过布置基本控制结构或建议替代我在 PHP 中执行此操作的方式来使此操作更快,从而让我开始。

这是基本的破败。代码如下。

我在摄入表中有一行,它可能与我的规范化提供者数据库中的现有提供者匹配,也可能不匹配。我有不同的数据元素,具体取决于行的完整性。

我当前的控制函数如下所示:它的工作是返回现有提供者的 ID,或者创建新的提供者然后返回该 ID。

    function find_provider($input){
    if (!$by_i_id = $this->find_provider_with_i_provider_id($input->i_provider_id)){
        //Not By I ID
        if (!$by_medicare_id = $this->find_provider_with_medicare_id($input->national_provider_id)){
            //Not by Medicare ID
            if (!$by_license_number = $this->find_provider_with_license_number($input->license)){
                //Not by License Number
                if (!$by_s_id_map = $this->find_provider_with_s_provider_id($input->source_id, $input->s_client_id, $input->s_provider_id)){
                    //Not By S_id
                    if (!$by_tax_id = $this->find_provider_with_tax_id($input->tax_id, $input->s_entity_type, $input->source_id, $input->last_name, $input->first_name)){
                        //Not by Tax Id
                        if (!$by_name = $this->find_provider_by_name($input->first_name, $input->last_name)){
                            //not by Name.
                            return $this->add_provider($input);
                        }else{
                            //At least 1 Name Match
                            if (count($by_name) == 1){
                                $by_name = $by_name[0]->provider_id;
                                if (!$by_address = $this->confirm_provider_by_address($input->address1, $input->zip, $by_name)){
                                    //Not a Match
                                    return $this->add_provider($input);
                                }else{
                                    return $by_name;
                                }
                            }else{
                                //More than 1 Match
                                $match = array();
                                Foreach ($by_name as $key => $row){
                                    If ($this->confirm_provider_by_address($input->address1, $input->zip, $row->provider_id) != FALSE){
                                        $match[] = $row->provider_id;
                                    }
                                }
                                if (count($match)> 0){
                                    return $match[0];
                                }else{
                                    return $this->add_provider($input);
                                }
                            }
                        }
                    }else{
                        return $by_tax_id;
                    }
                }else{
                    return $by_s_id_map;
                }
            }else{
                return $by_license_number;
            }
        }else{
            return $by_medicare_id;
        }
    }else{
        return $by_i_id;
    }
}

在此,我尝试首先通过内部 ID、Medicare ID、许可证、来源 ID、税号、姓名和地址进行匹配。

这些函数中的每一个看起来像这样:(etype 是一个实体类型,可能存在也可能不存在。而 Not This ID 是因为我第二次运行这些函数,寻找次要匹配,有时他们可以同时来自 2 个不同的提供商)。

    function find_provider_with_i_provider_id($provider_id, $etype = null, $notthisid=null){
    //Select from provider where 'id' == $provider_id
    if (is_int($provider_id)==true && $provider_id != 0){
        $this->db->select('id');
        $this->db->from('list_provider');
        $this->db->where('id', $provider_id);
        if (!$etype == null){
            $this->db->where('entity_type_id', $etype);
        }
        if (!$notthisid == null){
            $this->db->where('id !=', $notthisid);
        }
        $result = $this->db->get();

        if ($result->num_rows == 0){
            return false;
        }elseif ($result->num_rows == 1){
            //Call The Result Function to Pull the Data as an Object.
            $out = $result->result();
            return $out[0]->id;
            //return true;
        }else{
            $out = $result->result();
            //$this->log_event('find_provider_with_i_provider_id','error', 'Multiple Results for an Internal Provider ID', $provider_id);
            return $out[0]->id;
        }
    }else{
        return false;
    }
}

如您所见,这是大量的数据库工作,我必须处理很多行(目前在摄入表中为 3500 万行)。所以这是超级慢。

我试图弄清楚如何在 PHP 中更好地构造这个,或者更理想的是,我认为,将整个事情重新写入 pgsql,以便数据库可以预先计划和优化这一切。

我相信该数据库已被适当索引(所有选择和连接元素),但运行这 3500 万行仍然需要大约 2 周的时间。

想法?帮助?

如果您需要更多信息或有任何问题,请告诉我。数据库非常接近规范化,除了我必须为不同的用例复制一两条信息,而这些用例连接不起作用。它基本上是一个雪花图案。

4

1 回答 1

1

我认为您正在寻找类似的东西,您返回的表是您的过滤器返回的行数,以及“如何[可能]匹配”的所有选项的列。您的 PHP 将负责确定其匹配方式的优先级,但只需要一次查询和数据库往返。

CREATE OR REPLACE FUNCTION schema.function(
    IN  filter1                 integer,
    ...
    IN  filterN                 text
)
    RETURNS TABLE (
        id                      integer,
        reason1                     boolean,
        ...
        reasonN                     boolean
    )
    LANGUAGE plpgsql
    AS $body$
        DECLARE
        BEGIN
            RETURN QUERY
                SELECT
                    id,
                    CASE
                        WHEN reason1Criteria THEN true
                        ELSE false
                    END AS reason1,
                    ...
                    CASE
                        WHEN reasonNCriteria THEN true
                        ELSE false
                    END AS reasonN
                FROM tables
                WHERE
                    t.column1 = filter1 AND
                    ...
                    t.columnN = filterN;
        END;
    $body$;
于 2013-01-29T16:59:12.650 回答