Delete records from Postgresql - sql

I need to delete records from one table based on inner join condition on other two tables, however query runs for ages.
DELETE FROM public.blacklist WHERE subject_id NOT IN(
SELECT DISTINCT a.id FROM public.subject a
INNER JOIN stg.blacklist_init b ON a.subject_id=b.customer_code);
Any ideas how to achieve this?
Thank you.

You can use NOT EXISTS instead of NOT IN, and I think you don't need a DISTINCT
DELETE FROM public.blacklist bl
WHERE NOT EXISTS (
SELECT 0
FROM public.subject a
INNER JOIN stg.blacklist_init b
ON a.subject_id=b.customer_code
WHERE a.id = bl.subject_id
);

Related

How to find records that exist in all 4 tables? SQL Server 2008

I have to migrate records from one system to another. There is 4 different tables. First table contains all information about each user. Each row has unique ID that is primary key. So I need to grab primary key from table one and find matching record in other 3 tables. Those tables have foreign key that we should use to match users. Here is example:
SELECT *
FROM Users AS ur
WHERE EXISTS(
SELECT *
FROM TableA AS a
WHERE ur.ur_id = a.a_urid
)
//Maybe second option can be to use INNER JOIN
SELECT *
FROM Users AS ur
INNER JOIN TableA AS a
ON ur.ur_id = a.a_urid
INNER JOIN TableB AS b
ON ur.ur_id = b.b_urid
INNER JOIN TableC AS c
ON ur.ur_id = c.c_urid
Query above will return matching records only for Users and Table A. I'm wondering if I can match all records from Users table that have matching user ID in table A, B and C. How that can be achieved in SQL Server 2008? Or I would need to add/import each table individually? If anyone can help with this task please let me know. Thank you!
You can use intersect:
select u.id
from users u
intersect
select a.a_urid
from a
intersect
select b.b_urid
from b
intersect
select c.c_urid
from c;
Another way is to use exists:
SELECT ur.*
FROM Users ur
WHERE EXISTS (SELECT 1 FROM TableA AS a WHERE ur.ur_id = a.a_urid) AND
EXISTS (SELECT 1 FROM TableB AS b WHERE ur.ur_id = b.b_urid) AND
EXISTS (SELECT 1 FROM TableC AS c WHERE ur.ur_id = c.c_urid) ;
Using a JOIN, you have to be careful. The result set might contain duplicates. And removing the duplicates could be very expensive.

Convert SQL Server Delete statement to use inner join

My goal is to convert the below query to use inner join.
DELETE ##TABLE1
FROM ##TABLE1 A, ##TABLE2 B
WHERE A.VND_ACCT_NUM in (select distinct VND_ACCT_NUM from ##TABLE2)
I tried something like this but it doesn't seem right:
DELETE ##TABLE1
FROM ##TABLE1 A
INNER JOIN ##TABLE2 B
ON A.VND_ACCT_NUM in (select distinct VND_ACCT_NUM from ##TABLE2)
My task is to convert the first query to use the inner join syntax.
Just match the tables up directly:
DELETE FROM A
FROM ##TABLE1 A
INNER JOIN ##TABLE2 B
ON A.VND_ACCT_NUM i= B.VND_ACCT_NUM
SQL Server doesn't mind if you attempt to delete the same row multiple times by such a join. Also, the ... IN(SELECT DISTINCT ... was pointless anyway since IN returns true as soon as it has located one qualifying row.
Try this:
DELETE A
FROM ##MX_DEALS A
INNER JOIN ##MX_DAR_ISSUE_DEALS B
ON A.VND_ACCT_NUM in (select distinct VND_ACCT_NUM from ##MX_DAR_ISSUE_DEALS)

counting abscense or rows

I need to write a stored procedures to update contacts who have no active pledges in our database, I can't seem to find a way of counting contacts with 0 rows on the pledges table.
The external key in the pledges table is supporter_id, I've tried using Count(*), but it only returns 1 or more.
Thanks in advance.
PS: This is on a MS SQL database.
We'd need more information to give you a specific answer, but there are a number of ways to identify non-matching records, here are two:
LEFT JOIN:
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
WHERE b.ID IS NULL
NOT EXISTS:
SELECT *
FROM TableA a
WHERE NOT EXISTS (SELECT *
FROM TableB b
WHERE a.ID = b.ID)
I ended using a subquery so I first determine who has pledges of the type I want and then look for contacts who are not in that list.
thanks for the responses.

How to exclude rows that don't join with another table?

I have two tables, one has primary key other has it as a foreign key.
I want to pull data from the primary table, only if the secondary table does not have an entry containing it's key. Sort of an opposite of a simple inner join, which returns only rows that join together by that key.
SELECT <select_list>
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL
Full image of join
From aticle : http://www.codeproject.com/KB/database/Visual_SQL_Joins.aspx
SELECT
*
FROM
primarytable P
WHERE
NOT EXISTS (SELECT * FROM secondarytable S
WHERE
P.PKCol = S.FKCol)
Generally, (NOT) EXISTS is a better choice then (NOT) IN or (LEFT) JOIN
use a "not exists" left join:
SELECT p.*
FROM primary_table p LEFT JOIN second s ON p.ID = s.ID
WHERE s.ID IS NULL
Another solution is:
SELECT * FROM TABLE1 WHERE id NOT IN (SELECT id FROM TABLE2)
SELECT P.*
FROM primary_table P
LEFT JOIN secondary_table S on P.id = S.p_id
WHERE S.p_id IS NULL
If you want to select the columns from First Table "which are also present in Second table, then in this case you can also use EXCEPT. In this case, column names can be different as well but data type should be same.
Example:
select ID, FName
from FirstTable
EXCEPT
select ID, SName
from SecondTable
This was helpful to use in COGNOS because creating a SQL "Not in" statement in Cognos was allowed, but it took too long to run. I had manually coded table A to join to table B in in Cognos as A.key "not in" B.key, but the query was taking too long/not returning results after 5 minutes.
For anyone else that is looking for a "NOT IN" solution in Cognos, here is what I did. Create a Query that joins table A and B with a LEFT JOIN in Cognos by selecting link type: table A.Key has "0 to N" values in table B, then added a Filter (these correspond to Where Clauses) for: table B.Key is NULL.
Ran fast and like a charm.

SQL Delete based on condition in join

It is possible to delete records based on a satisfied condition with a join query?
For instance, I have a linking table joining 3 records. The query I have at the moment deletes records from this table where one of the id's isn't IN() an imploded Php array. I've come to realise that the query should only remove records from this table if the id's don't exist in the array and they belong to a certain other table based on the a link to another table.
For SQL Server, the command is slightly different:
DELETE FROM TableA
FROM TableA LEFT OUTER JOIN TableB ON TableA.Column = TableB.Column
WHERE TableB.Column IS NULL
No, that's not a typo, yes, you do need "FROM TableA" twice. At least, you need the second FROM (the first is optional). The following has the advantage that it works for both SQL Server and MySQL:
DELETE TableA
FROM TableA LEFT OUTER JOIN TableB ON TableA.Column = TableB.Column
WHERE TableB.Column IS NULL
I like to use EXISTS clauses for this:
DELETE FROM TableA
WHERE
<<put your array condition here>>
AND NOT EXISTS
(SELECT 1 FROM TableB Where TableB.ID=TableA.ID)
You can use :
DELETE Based on a Join:
DELETE A
FROM TableA AS A
LEFT OUTER JOIN TableB As B ON A.Id = B.TabaleAId
WHERE B.Column IS NULL
Delete With SubQuery:
DELETE
FROM TableA AS A
Where
A.id not in ( Select B.TabaleAId From Tab;eB As B )
or
DELETE FROM TableA
WHERE Not EXISTS
(
SELECT *
FROM TableB As B
Where B.TableAId = TableA.Id
)
DELETE Using Table Expressions:
With A
As
(
Select TableA.*
FROM TableA AS A
LEFT OUTER JOIN TableB As B ON A.Id = B.TabaleAId
WHERE B.Column IS NULL
)
Delete From A
DELETE FROM TableA
LEFT OUTER JOIN TableB
WHERE TableB.Column IS NULL
Will delete the records in tableA that don't have a corresponding record in TableB. Is that like what you are after?
DELETE FROM a
FROM TableA AS a LEFT OUTER JOIN TableB AS b
on a.CALENDAR_DATE = b.CALENDAR_DATE AND a.ID = b.ID
Where b.ID is null
You can first use the select statement and verify your records that you want to delete and then remove the select statement and add Delete FROM tablename with the above query syntax.
The easiest way to Delete based on join is as follow:
1.Write your query using SELECT statement instead of DELETE statement
SELECT COLUMNS
FROM Table1
INNER JOIN Table2 ON Table1.YYY = Table2.XXX
2.Replace SELECT COLUMNS with DELETE FROM TABLE
DELETE FROM Table1
FROM Table1
INNER JOIN Table2 ON Table1.YYY = Table2.XXX
Note that we need to specify FROM twice, one for DELETE part and one for JOIN part.
delete from TableA
where id in
(
select id from TableA
except select id from TableB
)
Which means "delete from tableA where id in table a but not in table b)
Otherwise a Merge statement might help you (when matched/not matched delete etc)
http://technet.microsoft.com/en-us/library/bb510625.aspx