SQL: How do I delete rows that are also in another table? - sql

Say I have two tables. E.g,
Table 1:
Store Product
1 2
1 1
2 3
2 4
And Table 2
Store Product
1 2
2 3
How do I delete all the rows in Table 1 that are also in Table 2?
So, new Table 1 would be:
Store Product
1 1
2 4

You seem want :
select t1.*
from table1 t1
where not exists (select 1
from table2 t2
where t2.store = t.store and
t2.product = t1.product
);
Similarly delete version would be :
delete
from table1 t1
where exists (select 1
from table2 t2
where t2.store = t.store and
t2.product = t1.product
);

You can use something like this:
DELETE
t1
FROM
table1 t1
WHERE
(t1.store, t1.product) IN ( SELECT
t2.store,
t2.product
from
table2 t2);

Related

prefer table 3 over table 2 and table 2 over table 1

I have 3 tables with names and number of few of my friends.
Table 3 has correct data, table 2 has minute errors in data and table 1 has more than table 2.
if a user exists in table 2 and 3 then show table 3 details in output else table 2 details, if user is not even there in table 2 then show user data from table1.
more like a preference order.
DUMMY DATA:
table 1 :
name phone
abc 2343
bcd 3434
ccd 3455
ffc 4545
table 2 :
name phone
abc 2313
bcd 3414
ccd 3415
table 3 :
name phone
abc 2344
bcd 3431
expected output :
name phone
abc 2344
bcd 3431
ccd 3415
ffc 4545
I tried this query but unable to find correct output.
select phone,
coalesce(table1.name, TABLE2.name,TABLE3.name) as namee
FROM TABLE1
left JOIN TABLE2
ON table1.name = table2.name
INNER JOIN table3
ON table3.name = table2.name
Would be a huge, huge heeelppppp.
Gordon was close; he had the preference backwards. Please make sure you understand why the script works.
-- grab all our preferred data first
select t3.*
from table3 t3
union all
-- grab anything that doesn't exist in our preferred table
select t2.*
from table2 t2
where not exists (select 1 from table3 t3 where t3.name = t2.name)
union all
-- grab anything that doesn't exist in our preferred tables
select t1.*
from table1 t1
where not exists (select 1 from table2 t2 where t2.name = t1.name) and
not exists (select 1 from table3 t3 where t3.name = t1.name);
Use union all:
select t1.*
from table1 t1
union all
select t2.*
from table2 t2
where not exists (select 1 from table1 t1 where t1.name = t2.name)
union all
select t3.*
from table3 t3
where not exists (select 1 from table1 t1 where t1.name = t3.name) and
not exists (select 1 from table2 t2 where t2.name = t3.name);

Update table if join table does not have rows

I have two tables which has relationships and I trying to update base table if there are no records in the child table.
Table1:
id value
1 abc
2 xyz
Table2:
id table1_id
1 1
2 1
So in this case I want to update table1 id 2 to pqr as it does not have associated rows in table2. For id 1 nothing happens.
I tried this way but this is completely wrong
update table1 set value = 'pqr'
from table1 t1 inner join table2 t2 on count(t2.table1_id) < 1
If you want to update the rows of table1 with ids that don't have a match in table2 in the column table1_id then you can do it with a LEFT JOIN and update the unmatched rows:
update t1
set t1.value = 'pqr'
from table1 t1 left join table2 t2
on t2.table1_id = t1.id
where t2.table1_id is null
See the demo.
Results:
> id | value
> -: | :----
> 1 | abc
> 2 | pqr
I believe you're looking for WHERE NOT EXISTS.
update table1
set value = 'pqr'
from table1 t1
WHERE
NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.table1_id = t1.id);
Although this assumes you're asking the question in the title, not the one in the test of your question.
UPDATE table1
SET value = 'pqr'
WHERE id IN (SELECT t1.id FROM table1 t1 INNER JOIN table2 t2 ON t1.id = t2.table1_id)

How can get a column where my result is 1 2 3 6 7 8 I want to exclude the common IDs from both the table and display the result in one column

Let's say I have Two tables T1 and T2 with ID as the column. For example
T1:ID
1
2
3
4
5
T2:ID
4
5
6
7
8
How can get a column where my result is 1 2 3 6 7 8 I want to exclude the common IDs from both the table and display the result in one column.
Hmmm . . . one method is union all:
select t1.id
from table1 t1
where not exists (select 1 from table2 t2 where t2.id = t1.id)
union all
select t1.id
from table2 t2
where not exists (select 1 from table1 t1 where t2.id = t1.id);
use minus
select id from
(
select id from t1
union
select id from t2
) a
minus select id from (
select id from t1 join t2 on t1.id=t2.id
) b
If your DBMS support FULL OUTER JOIN then i would do :
select coalesce(t1.id, t2.id)
from t1 full outer join
t2
on t2.id = t1.id
where (t1.id is null or t2.id is null);

Aggregate functions as column results from multiple tables

I have the following table structures:
Table1
--------------
Table1Id
Field1
Field2
Table2
------------
Table2Id
Table1Id
Field1
Field2
Table3
-----------
Table3Id
Table1Id
Field1
Field2
I need to be able to select all fields in Table1, count of records in Table2, and count of records in Table3 Where count of records in Table2 > count of records in Table3
Here is an example of expected output with the given data:
Table1 Data
-------------
1 Record1Field1 Record1Feild2
2 Record2Field1 Record2Feild2
3 Record3Field1 Record3Feild2
4 Record4Field1 Record4Feild2
Table2 Data
------------
1 1 Record1Field1 Record1Feild2
2 1 Record2Field1 Record2Feild2
3 2 Record3Field1 Record3Feild2
4 2 Record4Field1 Record4Feild2
5 2 Record5Field1 Record5Feild2
6 4 Record6Field1 Record6Feild2
7 4 Record6Field1 Record6Feild2
8 4 Record6Field1 Record6Feild2
Table3 Data
------------
1 2 Record1Field1 Record1Feild2
2 2 Record2Field1 Record2Feild2
3 3 Record3Field1 Record3Feild2
4 3 Record4Field1 Record4Feild2
5 3 Record5Field1 Record5Feild2
6 4 Record6Field1 Record6Feild2
Desired Results
Table1Id Field1 Field2 Table2Count Table3Count
1 Record1Field1 Record1Field2 2 0
2 Record2Field1 Recird2Field2 3 2
4 Record4Field1 Recird4Field2 3 1
Notice record 3 in Table 1 is not shown because the record count in Table2 is less than the record count in Table3. I was able to make this work using a very ugly query similar to the one below but feel there is a much better way to do this using joins.
SELECT
t1.Table1Id,
t1.Field1,
t1.Field2
(Select Count(Table2Id) From Table2 t2 Where t2.Table1Id = t1.Table1Id) as Table2Count,
(Select Count(Table3Id) From Table3 t3 Where t3.Table1Id = t1.Table1Id) as Table3Count,
From
Table1 t1
Where
(Select Count(Table2Id) From Table2 t2 Where t2.Table1Id = t1.Table1Id) > (Select Count(Table3Id) From Table3 t3 Where t3.Table1Id = t1.Table1Id)
Hard to test it without working examples but something along these lines should be a good starting point.
SELECT
t1.Table1Id,
t1.Field1,
t1.Field2,
COUNT(DISTINCT t2.Table2Id),
COUNT(DISTINCT t3.Table3Id)
From Table1 t1
LEFT OUTER JOIN Table2 t2 ON t1.Table1Id = t2.Table1Id
LEFT OUTER JOIN Table3 t3 ON t1.Table1Id = t3.Table1Id
GROUP BY t1.Table1Id
HAVING COUNT(DISTINCT t2.Table2Id) > COUNT(DISTINCT t3.Table3Id)
You could get all the value in t1 and the data form t2 e t3 for your comparision using a couple of join on grouped values
SELECT
t1.Table1Id
,t1.Field1
,t1.Field2
, tt2.count_t2
, tt3.count_t3
from table1 t1
join (
select Table1Id, count(*) count_t2
From Table2
group by Table1Id
) tt2 on tt2.Table1Id = t1.Table1Id
join (
select Table1Id, count(*) count_t3
From Table3
group by Table1Id
) tt3 on tt3.Table1Id = t1.Table1Id
where tt2.count_t2 < tt3.count_t3 <

Joining two tables in a select

I have two tables:
TABLE 1
ID VALUE
1 ABC
2 DEF
3 GHI
4 JKL
5 XYZ
TABLE 2
ID T1_ID VALUE
1 1 A
2 1 B
3 2 A
4 3 A
5 3 B
6 4 B
I want to select all rows from TABLE 1 which have a TABLE 2 row for Values A AND B.
This would be rows 1 and 3 (not 2 because it has only A, not 4 because it has only B).
Can I do this without a subquery?
(Note: I also need to query against values in table 1 so I can't just query table 2.)
Tadaaah! Without a subquery.
select distinct
t1.*
from
Table1 t1
inner join Table2 t2a on t2a.t1_ID = t1.ID and t2a.VALUE = 'A'
inner join Table2 t2b on t2b.t1_ID = t1.ID and t2b.VALUE = 'B'
SELECT t1.ID,
t1.VALUE
FROM Table1 t1
JOIN Table2 t2
ON t1.ID = t2.T1_ID
WHERE t2.VALUE IN ( 'A', 'B' )
GROUP BY t1.ID,
t1.VALUE
HAVING COUNT(DISTINCT t2.VALUE) = 2