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、次にメディケア ID、ライセンス、ソース ID、納税者 ID、名前と住所の順で照合を試みます。

これらの関数のそれぞれは次のようになります: (etype は、存在する場合も存在しない場合もあるエンティティ タイプです。また、Not This ID は、これらの関数を 2 回目に実行し、2 番目の一致を探しているためです。 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;
    }
}

ご覧のとおり、これは多くのデータベース作業であり、多くの行を処理する必要があります (現在、取り込みテーブルで 3,500 万)。これがスーパースローです。

PHPでこれをより適切に構造化する方法、またはより理想的には、このすべてをpgsqlに書き直して、データベースがこれをすべて事前に計画および最適化できるようにする方法を見つけようとしています。

データベースは適切にインデックス化されていると思いますが (すべての選択要素と結合要素)、これらの 3500 万行を実行するには、まだ 2 週間ほどかかります。

考え?ヘルプ?

さらに詳しい情報が必要な場合やご不明な点がございましたら、お知らせください。データベースは、結合が機能しないさまざまなユースケースで 1 つまたは 2 つの情報を複製する必要があったことを除いて、ほぼ正規化されています。基本的には雪の結晶のパターンです。

4

1 に答える 1

1

このようなものを探していると思います.返されたテーブルは、フィルターが返した行の数であり、「どのように一致するか」に関するすべてのオプションの列です。PHP は、どのように一致したかの優先度を決定する責任がありますが、必要なクエリとデータベースのラウンドトリップは 1 つだけです。

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 に答える