19
votes

Hi to all you mighty SQLsuperheros out there.. Can anyone rescue me from imminent disaster and ruin?

I'm working with Microsoft Access SQL. I'd like to select records in one table (table1) that don't appear in another (table2) .. and then insert new records into table2 that are based on records in table1, as follows:

[table1] file_index : filename

[table2] file_index : celeb_name

I want to:

Select all records from table1 where [filename] is like aud and whose corresponding [file_index] value does not exist in table2 with with field [celeb_name] = 'Audrey Hepburn'

With that selection I then want to insert a new record into [table2]

[file_index] = [table1].[file_index] [celeb_name] = 'Audrey Hepburn'

There is a one to many relationship between [file_index] in [table1] and [table2] One record in [table1], to many in [table2].

Many thanks

4

4 Answers

19
votes

Will this do? Obviously add some square brackets and stuff. Not too into Access myself.

INSERT INTO table2 (file_index, celeb_name)
SELECT file_index, 'Audrey Hepburn'
FROM table1
WHERE filename = 'aud'
  AND file_index NOT IN (SELECT DISTINCT file_index 
                         FROM table2 
                         WHERE celeb_name = 'Audrey Hepburn')
2
votes

As I said in comments, NOT IN is not well-optimized by Jet/ACE and it's usually more efficient to use an OUTER JOIN. In this case, because you need to filter on the outer side of the join, you'll need a subquery:

  INSERT INTO photos_by_celebrity ( ORIG_FILE_INDEX, celebrity_name )
  SELECT tblOriginal_Files.ORIG_FILE_INDEX, 'Audrey Hepburn'
  FROM tblOriginal_Files 
    LEFT JOIN (SELECT DISTINCT ORIG_FILE_INDEX  
                  FROM photos_by_celebrity 
                  WHERE celebrity_name = 'Audrey Hepburn') AS Photos
    ON tblOriginal_Files.ORIG_FILE_INDEX = Photos.ORIG_FILE_INDEX
  WHERE Photos.ORIG_FILE_INDEX Is Null;

(that may not be exactly right -- I'm terrible with writing SQL by hand, particularly getting the JOIN syntax right)

I must say, though, that I'm wondering if this will insert too many records (and the same reservation applies to the NOT IN version).

0
votes

In the original question I'd modified my table and field names and inserted square brackets in to make it easier to read.

Below is the final SQL statement that worked in MS Access format. Awesome result, thanks again Tor!!

INSERT INTO photos_by_celebrity ( ORIG_FILE_INDEX, celebrity_name )

SELECT tblOriginal_Files.ORIG_FILE_INDEX, 'Audrey Hepburn' AS Expr1

FROM tblOriginal_Files

WHERE (((tblOriginal_Files.ORIG_FILE_INDEX) Not In (SELECT DISTINCT ORIG_FILE_INDEX 

                         FROM photos_by_celebrity  

                         WHERE celebrity_name = 'Audrey Hepburn')) AND ((tblOriginal_Files.ORIGINAL_FILE) Like "*aud*"));
0
votes

You can use NOT Exists

I think it is the best way from the side of performance.

As Follow:

INSERT INTO table2 (file_index, celeb_name)
SELECT file_index, 'Audrey Hepburn'
FROM table1
WHERE filename = 'aud'
  AND NOT Exists (SELECT file_index 
                         FROM table2 
                         WHERE celeb_name = 'Audrey Hepburn')