开发者

SQL INSERT from SELECT producing duplicate records

I'm learning PHP and Zend Framework. The following PHP function is supposed to fill a temporary table using "INSERT INTO ... SELECT" style query. However, when I SELECT * from the newly appended table, I see that most but not all of the new records have been duplicated once. I have deleted the contents of the table each time I run this scripts. Anyone know why there would be duplicates?

public function fillTableByOfficeName($officeName) {
    if ($officeName != '') {
        $officePhrase = "b.oof_name ='" . $officeName . "' AND ";
    } else {
        $o开发者_Go百科fficePhrase = '';
    }

    $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;
}


The way you are joining the table will give you the cartesian product of the rows from the tables (all pairs of matching rows are returned).

With no specific knowledge of the domain, I would guess at the tags table - if you've got multiple tags for a particular file, you will get multiple copies of the file in your result set (one per each matched tag).

As you're not using tags fields in the result set, just the where clause, the solution would be to get rid of tags / nn_files_tags from the main query, and in your where clause, use NOT EXISTS to check for matching rows in the tags table, something like:

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


You are using C for a many to many relationship. For example, if you have invoices between companies and customers and you select from join of them, you will get as many rows as you have invoices. From that, if you only select the company name and costumer name, you will have many duplicates because the same pair has produced many invoices.

This is the same issue you have here.

As asc99c said, you could use an inner select to make your WHERE clause without joining on that relationship or you could use the DISTINCT key word (which effectively is a group by on everything in your SELECT clause). I would think the INNER SELECT solution more efficient (yet I could be totally wrong about that), but the DISTINCT way is 8 key press away...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜