SELECT的SQL INSERT生成重复记录

时间:2011-09-01 22:44:57

标签: php sql zend-framework

我正在学习PHP和Zend Framework。以下PHP函数应该使用“INSERT INTO ... SELECT”样式查询来填充临时表。但是,当我从新附加的表中选择SELECT *时,我发现大多数但并非所有的新记录都被重复了一次。每次运行此脚本时,我都删除了表的内容。任何人都知道为什么会有重复?

public function fillTableByOfficeName($officeName) {
    if ($officeName != '') {
        $officePhrase = "b.oof_name ='" . $officeName . "' AND ";
    } else {
        $officePhrase = '';
    }

    $whereAddenda = $officePhrase .
            "a.fil_bool_will_file_online = false AND " .
            "a.fil_bool_confirmed = false AND " .
            "a.fil_bool_duplicate = false AND " .
            "a.fil_bool_not_found = false AND " .
            "(a.fil_res_id_fk NOT IN (4,7,10) OR a.fil_res_id_fk IS NULL) AND " .
            "a.fil_will_recorder_rec_id IS NULL AND " .
            "d.tag_description NOT IN (
                'Already a trust client',
                'Not received from local office',
                'Southtrust client (already centralized)')";
            //"a.fil_date_of_transfer_to_will_recorder IS NULL";

    $sql = "INSERT INTO adds(fil_id,REC_ID,FIRST_NAME,LAST_NAME,MIDDLE_INITIAL,SSN," .
          "MAILING_ADDRESS_1,MAILING_ADDRESS_2,CITY,STATE,ZIP_CODE,PHONE_NUMBER,BIRTH_DATE," .
          "ORIGINATION_OFFICE,FILE_LOCATION,WILL_DATE,LAST_CODICIL_DATE,TRUST_DATE,REV_TRUST,POA_DATE) " .
          "SELECT a.fil_id_pk, " .
                "a.fil_will_recorder_rec_id, " .
                "a.fil_first_name, " .
                "a.fil_last_name, " .
                "a.fil_middle_name, " .
                "a.fil_ssn, " .
                "a.fil_mailing_address_1, " .
                "a.fil_mailing_address_2, " .
                "a.fil_city_address, " .
                "a.fil_state_address, " .
                "a.fil_zip_code_fk, " .
                "a.fil_phone_number, " .
                "a.fil_date_of_birth, " .
                "b.oof_name, " .
                "a.fil_box_id_fk, " .
                "a.fil_date_of_will, " .
                "a.fil_date_of_last_codicil, " .
                "a.fil_date_of_trust, " .
                "a.fil_notes, " .
                "a.fil_date_of_poa " .
          "FROM files a, origination_offices b, nn_files_tags c, tags d " .
          "WHERE " .
                "a.fil_oof_id_fk = b.oof_id_pk AND " .
                "a.fil_id_pk = c.fil_id_fk AND " .
                "d.tag_id_pk = c.tag_id_fk AND " .
                 $whereAddenda;
    $this->getAdapter()->query($sql);
    return $this;
}

2 个答案:

答案 0 :(得分:1)

您加入表格的方式将为您提供表格中行的笛卡尔积(返回所有匹配行对)。

由于没有关于域的具体知识,我猜猜标签表 - 如果您有特定文件的多个标签,您将在结果集中获得该文件的多个副本(每个匹配标签一个)

由于你没有在结果集中使用标签字段,只有where子句,解决方案是从主查询中删除标签/ nn_files_tags,在你的where子句中,使用NOT EXISTS来检查匹配标签表中的行,如:

AND NOT EXISTS (SELECT tag_id_pk FROM tags WHERE tags.tag_id_pk ...

答案 1 :(得分:0)

您正在使用C进行多对多关系。例如,如果您在公司和客户之间有发票并且您从他们的加入中选择,则您将获得与发票一样多的行。由此,如果您只选择公司名称和客户名称,您将有许多重复项,因为同一对已生成许多发票。

这是你在这里遇到的同样问题。

正如asc99c所说,您可以使用内部选择来创建WHERE子句而不加入该关系,或者您可以使用DISTINCT关键字(实际上是SELECT子句中的所有内容)。我认为INNER SELECT解决方案更有效率(但我可能完全错了),但DISTINCT方式是8键按下...