Avoiding join in MS Access delete query - sql

I am trying to create a delete query to remove records from one table, based on whether or not one of the field exists in another master table. The situation is that I am importing new records into a database, but I want to remove the records that have already been imported, i.e. that already have an account in the master table. The field I need to join on, however is not equal: it is prefixed with a constant three letter code XYZ.
tbl_to_import.Account master_table.Account
123456 XYZ.123456
345678 XYZ.345678
To avoid using a join in the delete query I tried the following:
Delete tbl_to_import.*
From tbl_to_import
Where Exists( Select master_table.Account From master_table
Where master_table.Account = ("XYZ."& tbl_to_import.Account) ) = True;
However, the query gets hung up in Access. I'm not sure what I'm doing incorrectly. I don't get an error message, but the query runs without producing anything and I eventually stop it. In this situation, tbl_to_import has 2,700 records and master_table has 50,000 records. Additionally, I am connecting to the master_table via ODBC.
Originally, I constructed two queries using a join to perform the delete. tbl_to_import.Account has a primary key called ID. One query, qry_find_existing_accounts, located the ID numbers in tbl_to_import for which there exists a corresponding account in master_table.Account:
SELECT DISTINCTROW tbl_to_import.ID AS DELETEID
FROM tbl_to_import LEFT JOIN master_table
ON ("XYZ."& tbl_to_import.Account) = master_table.Account
WHERE ((("XYZ." & [Account])=[master_table].[Account]));
Then I used this query to construct the delete query:
DELETE DISTINCTROW tbl_to_import.*, tbl_to_import.ID
FROM tbl_to_import RIGHT JOIN qry_find_existing_accounts
ON tbl_to_import.ID =qry_find_existing_accounts.DELETEID
WHERE (((tbl_to_import.ID)=[qry_find_existing_accounts].[DELETEID]));
The query qry_find_existing_accounts worked fine; however, when I tried to run the second query to delete, I got the error: Could not delete from specified tables. Typically, when I get this error, it is because I have not selected unique records only, however, I used DISTINCTROW in both queries.
Any ideas what I am doing wrong and how I can accomplish what I need to do?

I'd go with a simpler nested SQL statement:
Delete tbl_to_import.*
From tbl_to_import
Where "XYZ." & tbl_to_import.Account In
(Select master_table.Account From master_table);
This should be fairly fast, especially if your Account fields are indexed.

I think you can simplify the query; delete based on the ID, where the IDs are in the query:
DELETE * FROM tbl_to_import
WHERE tbl_to_import.ID IN (
SELECT DISTINCT [DELETED] FROM qry_find_existing_accounts
)

Related

Best way to "SELECT *" from multiple tabs in sql without duplicate?

I am trying to retrieve every data stored in 2 tabs from my database through a SELECT statement.
The problem is there are a lot of columns in each tab and manually selecting each column would be a pain in the ass.
So naturally I thought about using a join :
select * from equipment
join data
on equipment.id = data.equipmentId
The problem is I am getting the equipment ID 2 times in the result.
I thought that maybe some specific join could help me filter out the duplicate key, but I can't manage to find a way...
Is there any way to filter out the foreign key or is there a better way to do the whole thing (I would rather not have to post process the data to manually remove those duplicate columns)?
You can use USING clause.
"The USING clause specifies which columns to test for equality when
two tables are joined. It can be used instead of an ON clause in the
JOIN operations that have an explicit join clause."
select *
from test
join test2 using(id)
Here is a demo
You can also use NATURAL JOIN
select *
from test
natural join test2;

Error #1093 - Table is specified twice, both as a target for 'DELETE' and as a separate source for data

I'm trying to delete duplicate rows in a table. The email field needs to be be unique in the table for the code after it to run. Here's my code:
DELETE FROM deleteRequests
WHERE Email NOT IN (
SELECT MAX(Email)
FROM deleteRequests
GROUP BY email);
The error I get is: '#1093 - Table 'deleteRequests' is specified twice, both as a target for 'DELETE' and as a separate source for data'
I think the problem is that I'm using mariadb 10.2 (which also means I can't use WITH CTE). I am not in control of updating this, so I need a workaround. Suggestions?
MySQL, MariaDB doesn't allow the table to be referenced again in a DELETE or UPDATE. An easy work-around is to use a JOIN:
DELETE dr
FROM deleteRequests dr LEFT JOIN
(SELECT MAX(email) as max_email
FROM deleteRequests
GROUP BY email
) dr2
ON dr2.email = dr.max_email
WHERE dr2.max_email IS NOT NULL;
Of course, this query is non-sensical because you are aggregating by email and choosing the max -- so all non-NULL emails will match.
Perhaps you want HAVING COUNT(*) = 1 in the subquery,.
I ended up creating a new table to work from.
CREATE TABLE deleteRequestsWorking as
SELECT MAX(mamaID) as mamaID, Email
FROM deleteRequests
GROUP BY mamaID;
This gave me the table I needed, and so instead of trying to get it to update my original table by using a LEFT JOIN and DELETE, I just used it. They're both temporary tables that get deleted at the end of the process, so it works.

Nesting SQL queries

I have the following SQL query. In this query, I am left joining a table tblTestImport with access query named "unique". I am trying to integrate the query "unique" into the code below. I am not having any luck, please help.
DELETE tblTestImport.ID
FROM tblTestImport
WHERE tblTestImport.[ID]
in (SELECT tblTestImport.ID
FROM tblTestImport
LEFT JOIN **[unique]**
ON tblTestImport.ID = **unique.**LastOfID
WHERE (((**unique.**LastOfID) Is Null)));
Code for "unique" query
SELECT Last(tblTestImport.ID) AS LastOfID
FROM tblTestImport
GROUP BY tblTestImport.Url, tblTestImport.Kms, tblTestImport.Price, tblTestImport.Time;
Further info: I am trying to delete duplicates from the Access Table, and leave unique ones only.
tblTestImport has duplicate records. "Unique" query displays unique records. Then, I join tblTestImport table with "unique" query, to determine which unique records do not exist in tblTestImport. This gives me a list duplicates, which I want to delete.
Within the big chunk of code, i have [unique], which I would like replace with small piece of code below.
Your query will return no results, assuming that id is never NULL.
Why? Well unique.lastOfId is always a valid id in tblTestImport. As such, the LEFT JOIN will always match, and lastOfId will never be NULL.
So, no rows are in the subquery.
My suggestion is that you ask another question. Explain what you want to do and provide sample data and desired results.
It's hard to tell exactly what you're after based on the current setup of your question. However, this may be what you're looking for:
DELETE tblTestImport.ID
FROM tblTestImport
WHERE tblTestImport.[ID] IN
(SELECT tblTestImport.ID
FROM tblTestImport
LEFT JOIN [unique] ON tblTestImport.ID = unique.LastOfID
WHERE unique.LastOfID Is Null
AND tblTestImport.ID IN (
SELECT Last(tblTestImport.ID) AS LastOfID
FROM tblTestImport
GROUP BY tblTestImport.Url, tblTestImport.Kms, tblTestImport.Price, tblTestImport.Time)
)
(This is a simple nested query in the previous query, but it would all depend on the relationship of the data itself. This query assumes that they are linked on the same tblTestImport.ID field)
Try the following, untested:
DELETE FROM tblTestImport
WHERE ID <> (SELECT Min(ID) AS MinOfID FROM tblTestImport AS Dupe
WHERE (Dupe.Url= tblTestImport.Url)
AND (Dupe.Kms= tblTestImport.Kms)
AND (Dupe.Price= tblTestImport.Price)
AND (Dupe.Time= tblTestImport.Time));
Solution based on the following http://allenbrowne.com/subquery-01.html

Cannot update a table using a simple inner join

I have 2 tables in access 2007.
See attached picture to see the structure of the tables and the expected result.
I am trying to update the quantity field (ITQTY) in TABLE_BLNC by summarizing all the quantity field (LOCQTY) from TABLE_DTL for same items (LOITNBR=ITNBR).
In TABLE_BLNC, the item is unique while in TABLE_DTL, the item can be in multiple records.
My query is:
UPDATE TABLE_BLNC INNER JOIN
(
SELECT LOITNBR, Sum(LOCQTY) AS SumOfLOCQTY FROM TABLE_DTL GROUP BY LOITNBR) AS DTL
ON TABLE_BLNC.ITNBR=DTL.LOITNBR SET TABLE_BLNC.ITQTY = DTL.SumOfLOCQTY;
I am getting the error:
Operation must use an updateable query.
Domain Aggregate functions can be useful when Access complains that an UPDATE is not updateable. In this case, use DSum() ...
UPDATE TABLE_BLNC
SET ITQTY =
DSum("LOCQTY", "TABLE_DTL", "LOITNBR='" & ITNBR & "'");
Index TABLE_DTL.LOITNBR for optimum performance.
One of the great annoyances of Access SQL is its inability to update a table from an non-updatable source. Non-updatable sources include read-only links to ODBC tables, and GROUP BY (summary) queries.
What I always do is:
Copy the structure of TABLE_BLNK to a temp table: TABLE_BLNK_temp.
In your code, first delete the temp:
DELETE * FROM TABLE_BLNK_temp;
Insert the result of your summary query into temp:
INSERT INTO TABLE_BLNK_temp (ITNBR, ITQTY)
SELECT LOITNBR, Sum(LOCQTY) AS SumOfLOCQTY
FROM TABLE_DTL GROUP BY LOITNBR;
Update TABLE_BLNK from TABLE_BLNK_temp:
UPDATE TABLE_BLNC INNER JOIN TABLE_BLNK_temp AS t
ON TABLE_BLNC.ITNBR = t.ITNBR
SET TABLE_BLNC.ITQTY = t.ITQTY;
While it is an extra step or two, this approach:
Always works
Is more performant than Domain Aggregate functions for larger datasets

Concatenating fields

This is an MS Access (2010) script.
I am trying to concatenate 2 fields of a single table for 2 tables. Then I want to delete the associated record in one of the table if the concatenated field is equal in both tables (means this is a duplicate).
I know how to do that in VBA by looping through the records but I want to do that in SQL since the tables may quickly hold more than 50000 records which means the loop would go 2,500,000,000 times.
I though I could create a 2 SELECT statement in order to create the concatenated fields for both tables. The SELECT Statements will also display the ID of the underlying tables. Then I would delete the record in the appropriate table using the ID.
These are my Select statements:
SELECT [Tick] & [Div_ex_date] AS Expr2, tblBbgDivData.ID
FROM tblBbgDivData
GROUP BY [Tick] & [Div_ex_date], tblBbgDivData.ID;
And
SELECT [Security_Name] & [Div_ex_date] AS Expr1, tblArchiveBbgDivData.ID
FROM tblArchiveBbgDivData
GROUP BY [Security_Name] & [Div_ex_date], tblArchiveBbgDivData.ID;
This is my DELETE Statement:
DELETE tblArchiveBbgDivData.*
FROM (tblArchiveBbgDivData
INNER JOIN qselUniqueID_Archive ON tblArchiveBbgDivData.ID = qselUniqueID_Archive.ID)
INNER JOIN qselUniqueID_BbgDiv ON qselUniqueID_Archive.Expr1 = qselUniqueID_BbgDiv.Expr2
WHERE (((tblArchiveBbgDivData.ID)=[qselUniqueID_Archive].[ID])
AND ((qselUniqueID_Archive.Expr1)=[qselUniqueID_BbgDiv].[Expr2]));
When I hit Datasheet view, the relevant records are displayed but when I hit Run I get "Could not delete from specified tables". Any idea how I can change that?
Access does not work well with JOINs in a DELETE statement. You may be better off with an IN:
DELETE tblArchiveBbgDivData.*
FROM (tblArchiveBbgDivData
WHERE tblArchiveBbgDivData.ID IN
(SELECT qselUniqueID_Archive.ID
FROM qselUniqueID_Archive )
INNER JOIN qselUniqueID_BbgDiv
ON qselUniqueID_Archive.Expr1 = qselUniqueID_BbgDiv.Expr2
);
Note that your WHERE is redundant because you use the same expression in your JOIN syntax.