Trying to get my delete statement to work - sql

I want to remove rows from a table, based on a column from another table as such:
Table1: Table2:
value value, i
If table2.i is less than 1, delete corresponding row from table1 (but keep it in table2).
The problem is that value isn't unique, so if I have this for exampe:
Table1 table2
+-------+ +-----------+
| value | | value | i |
+-------+ +-----------+
| 5 | | 5 | 0 |
| 3 | | 5 | 3 |
+-------+ | 3 | 0 |
| 3 | 0 |
+-----------+
Value 3 should be deleted from table1 (since all occurrences in table2 has i<1) but value 5 should stay(because of i=3 row in table2)
My code so far (doesn't work):
DELETE FROM Table1, Table2
WHERE (SELECT MIN(Table2.i) FROM Table1, Table2
WHERE Table1.value = Table2.value) < 1;
Problem is: since my subquery returns min for ALL rows, everything gets deleted.
And I can't use "group by" in my subquery because then my comparison isn't allowed.

Try this one:
DELETE FROM Table1
WHERE NOT EXISTS(SELECT 1
FROM Table2
WHERE Table2.i > 0
AND Table2.value = Table1.value)

I dont know why you are using min, instead u should use max:
try this
DELETE FROM Table1
WHERE Table1.value1 = Table2.value1
and (SELECT MAX(Table2.i) FROM Table2
WHERE Table1.value1 = Table2.value1) < 1;

Ok, I'd start by writing a query that selects the rows you want to delete,
SELECT
*
FROM
Table1
EXCEPT
(
SELECT
t1.value
FROM
Table1 t1
JOIN
Table2 t2
ON t2.value = t1.value
WHERE
t2.i > 0
);
See Fiddle
Then change the SELECT to a DELETE
DELETE Table1
FROM
Table1 t1
WHERE
t1.value NOT IN
(
SELECT
t1.value
FROM
Table1 t1
JOIN
Table2 t2
ON t2.value = t1.value
WHERE
t2.i > 0
);
See Fiddle

How about:
delete from table1 where value in
(select value from table2 group by value having max(i) < 1)
Grouping table 2 by value and using having to detect where the maximum is less than 1 allows you to select the correct values for deletion from table 1.
having is basically a where clause which comes into play after aggregation so can be used with max and so on.
Here's a script to show it in action:
DROP TABLE TABLE1;
DROP TABLE TABLE2;
CREATE TABLE TABLE1 (VALUE INTEGER);
CREATE TABLE TABLE2 (VALUE INTEGER, I INTEGER);
INSERT INTO TABLE1 VALUES (5);
INSERT INTO TABLE1 VALUES (3);
INSERT INTO TABLE2 VALUES (5, 0);
INSERT INTO TABLE2 VALUES (5, 3);
INSERT INTO TABLE2 VALUES (3, 0);
INSERT INTO TABLE2 VALUES (3, 0);
SELECT * FROM TABLE1;
SELECT * FROM TABLE2;
DELETE FROM TABLE1 WHERE VALUE IN
(SELECT VALUE FROM TABLE2 GROUP BY VALUE HAVING MAX(I) = 0);
SELECT * FROM TABLE1;
SELECT * FROM TABLE2;
The output of this script is shown below. First, the setting up of all the tables:
DROP TABLE TABLE1; DROP TABLE TABLE2;
TABLE1 DROPPED
TABLE2 DROPPED
CREATE TABLE TABLE1 (VALUE INTEGER);
TABLE1 CREATED
CREATE TABLE TABLE2 (VALUE INTEGER, I INTEGER);
TABLE2 CREATED
INSERT INTO TABLE1 VALUES ((5), (3));
INSERTED 2 ROWS
INSERT INTO TABLE2 VALUES ((5, 0), (5, 3), (3,0), 3, 0));
INSERTED 4 ROWS
And display them to ensure they're as expected:
SELECT * FROM TABLE1; SELECT * FROM TABLE2;
VALUE
-----
5
3
VALUE I
----- -
5 0
5 3
3 0
3 0
Then run the command to get rid of the relevant rows:
DELETE FROM TABLE1 WHERE VALUE IN
(SELECT VALUE FROM TABLE2 GROUP BY VALUE HAVING MAX(I) = 0);
DELETED 1 ROW
And you can see that the 3` row has disappeared from table 1 as desired:
SELECT * FROM TABLE1; SELECT * FROM TABLE2;
VALUE
-----
5
VALUE I
----- -
5 0
5 3
3 0
3 0

Related

Find number of non-unique column values within a group where a second column value is all the same

I have two tables.
Table 1:
id_a,
id_b,
id_t
Table 2:
id_t,
name
If Table 2 name starts with a, I need to find out of anything
with matching id_ts also have matching id_as.
If Table 2 name starts with b, I need to find out of any row
with matching id_ts also have matching id_bs.
I need to know how many times these matches occur.
Table 1
id_a
id_b
id_t
1
0
123
1
0
123
2
0
123
0
4
456
0
4
456
0
5
456
0
5
456
0
5
456
0
6
456
0
7
456
Table 2
id_t
name
123
aaq
456
bws
So in this example, I want to see a result like
id_t
name
num_non_unique
123
aaq
1
456
bws
2
My current code is this:
SELECT
t2.id_t, t2.name, count(t1.*) AS num_non_unique
FROM
Table 2 AS t2
JOIN Table 1 as t1 ON t2.id_t = t1.id_t
WHERE
(t2.name like 'a%' and t1.id_a in (SELECT id_a FROM t1 GROUP BY id_a, id_t HAVING count(*) > 1))
OR (t2.name like 'b%' AND t1.id_b IN (SELECT id_b FROM t1 GROUP BY id_b, id_t HAVING count(*) > 1))
GROUP BY t1.name, t1.id_t
This doesn't currently give me the results I want.
With this code I seem to get the count of all available rows for id_b, and 1 + non_uniques for id_a (so with one non-unique, the value is 2, otherwise the column has a 1).
Any help is appreciated!
Schema and insert statements:
create table table_1(id_a int, id_b int, id_t int);
insert into table_1 values(1, 0, 123);
insert into table_1 values(1, 0, 123);
insert into table_1 values(2, 0, 123);
insert into table_1 values(0, 4, 456);
insert into table_1 values(0, 4, 456);
insert into table_1 values(0, 5, 456);
insert into table_1 values(0, 5, 456);
insert into table_1 values(0, 5, 456);
insert into table_1 values(0, 6, 456);
insert into table_1 values(0, 7, 456);
create table table_2 (id_t int, name varchar(50));
insert into table_2 values(123, 'aaq');
insert into table_2 values(456, 'bws');
Query:
with case1 as
(
select id_t, id_a
from table_1
group by id_t, id_a
having count(*)=1
),
case2 as
(
select id_t,id_b
from table_1
group by id_t,id_b
having count(*)=1
)
select id_t,name,
(case when t2.name like 'a%' then (select count(*) from case1 where case1.id_t=t2.id_t) when t2.name like 'b%' then (select count(*) from case2 where case2.id_t=t2.id_t) end)num_non_unique
from table_2 as t2
Output:
id_t
name
num_non_unique
123
aaq
1
456
bws
2
db<fiddle here
If I understand correctly, you want the count -- for each row in table_2 -- of the corresponding rows in table_1 where id_b only appears once.
One method is:
select t2.*, coalesce(cnt, 0)
from table_2 t2 left join
(select id_a, count(*) as cnt
from (select id_a, id_b
from table_1
group by id_a, id_b
having count(*) = 1
) t1
group by id_a
) t1
on t1.id_a = t2.id_a;
Try this Code:
select name,id_ts,sum(count_) "num_non_unique" from
(
select t1.id_a,t1.id_b,t1.id_ts,t2.name, count(*) "count_"
from tab1 t1
inner join tab2 t2 on t1.id_ts=t2.id_t
group by 1,2,3,4
having count(*)=1
)tab
group by 1,2
Explanation:
As you have mentioned in your question that one column value will always be same based of name starting character. So no need to check the starting of the name in your query.
Simply we will check the count of unique row and filter it by using condition having count(*)=1.
After getting the unique row simply group it to get the count of rows group by name and id_ts
DEMO

MERGE with multiple UPDATE statements

Can we achieve below scenario using single MERGE statement:
source table - table1
destination table- table2
when table1.id in table2.id
then update table1 SET phone_number=123456
when table1.id not in table2.id
then update table1 SET phone_number=555555
Note:- i am able to achieve the result using below query .
MERGE INTO table1 tbl1
USING table2 tbl2
ON (tbl1.id = tbl2.id)
WHEN MATCHED THEN
UPDATE SET tbl1.phone_number=123456;
update table1 set phone_number = 555555 where id not in (select id from table2);
Is there any way to achieve it by using only MERGE Statement ?
When no rows are matched then you can not use UPDATE (in WHEN NOT MATCHED). as there are no rows matched then which data should be updated?
Normal merge statement must have following structure:
MERGE <hint> INTO <table_name>
USING <table_view_or_query>
ON (<condition>)
WHEN MATCHED THEN <update_clause>
DELETE <where_clause>
WHEN NOT MATCHED THEN <insert_clause>
[LOG ERRORS <log_errors_clause> <reject limit <integer | unlimited>];
When there is no match then there are no rows found by oracle into your target table which matches with source table using ON condition then how can it update the record? which record it will update?
WHEN NOT MATCHED is illustrated as following in oracle documentation:
You can handle your scenario using MERGE as follows:
-- Oracle data creation
SQL> CREATE TABLE table1 ( id number, phone_number number );
Table created.
SQL> INSERT INTO table1
2 SELECT 1, 111 from dual UNION ALL
3 SELECT 2, 222 from dual UNION ALL
4 SELECT 3, 333 from dual UNION ALL
5 SELECT 4, 444 from dual;
4 rows created.
SQL> drop table table2;
Table dropped.
SQL> CREATE TABLE table2 ( id number );
Table created.
SQL> INSERT INTO table2
2 SELECT 1 from dual UNION ALL
3 SELECT 2 from dual;
2 rows created.
-- Your merge statement
SQL> MERGE INTO TABLE1 TBL1
2 USING (
3 SELECT T1.ID, T2.ID AS T2ID
4 FROM TABLE1 T1
5 LEFT JOIN TABLE2 T2 ON T1.ID = T2.ID
6 )
7 TBL2 ON ( TBL1.ID = TBL2.ID )
8 WHEN MATCHED THEN
9 UPDATE SET TBL1.PHONE_NUMBER = NVL2(TBL2.T2ID, 123456, 555555);
4 rows merged.
-- Result
SQL> SELECT * FROM TABLE1;
ID PHONE_NUMBER
---------- ------------
1 123456
2 123456
3 555555
4 555555
SQL>
Cheers!!
Just use an UPDATE statement:
Oracle Setup:
CREATE TABLE table1 ( id, phone_number ) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 2, 2 FROM DUAL;
CREATE TABLE table2 ( id ) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 3 FROM DUAL;
Update:
UPDATE table1 t1
SET phone_number = COALESCE(
(
SELECT 123456
FROM table2 t2
WHERE t1.id = t2.id
),
555555
)
Output:
SELECT *
FROM table1
ID | PHONE_NUMBER
-: | -----------:
1 | 123456
2 | 555555
db<>fiddle here
The syntax you are looking for in a MERGE statement exists in SQL Server but is NOT valid in Oracle:
MERGE INTO table1 t1
USING table2 t2
ON ( t1.id = t2.id )
WHEN MATCHED THEN
UPDATE SET phone_number = 123456
WHEN NOT MATCHED BY SOURCE THEN
UPDATE SET phone_number = 555555;
db<>fiddle here

SQL Query Syntax Error using select & <> with 2 columns

I got a table with 2 columns here.
| column1 | column2 |
| A | 1 |
| B | 1 |
| C | 2 |
| D | 1 |
I'm trying to execute a SELECT query that:
Selects a value FROM Column 2 WHILE Column 2 doesn't have the same value in a row which has Column 1 = "A"
SELECT column2 from mytable and column2 <> (SELECT * FROM mytable where column1 = 'A');
Basically I'm trying to execute a query that returns column1 values only when column2 is valued at "2" here.
But the project I'm making will be having column2 values random so I should use only columns names
Sorry if that's too confusing!
The subquery of your query returns multiple values. So you have to use NOT IN instead of <>:
SELECT column2
FROM mytable
WHERE column2 NOT IN (SELECT column2 FROM mytable WHERE column1 = 'A');
use corelated subquery
select t1.* from mytable t1
where not exists ( select 1 from mytable t2 where t2.column2=t1.column2 and column1='A')
or use not in
select t1.* from table_name t1 where t1.column2 not in ( select column2 from table_name where column1='A')
You could also use a join, for example:
select t1.column2
from mytable t1 left join
(select distinct t2.column2 from mytable t2 where t2.column1='A') t3 on t1.column2=t3.column2
where t3.column2 is null

Multiple records for same id and i don't want to pull if id is not matching

I have a table 1 which is like this:
Id Values
100 1
100 2
100 3
110 1
110 2
110 4
120 3
I want the id where there is no 1 and 2 so my result should be like this
ID Values
120 3
you could try something like this.
SELECT id
,values_t
FROM Table1 t1
WHERE NOT EXISTS (
SELECT 1
FROM Table1 t2
WHERE t1.id = t2.id
AND t2.values_t IN (
1
,2
)
);
Fiddle
This makes a select of all data without id=1 or id=2
SELECT *
FROM Table2
WHERE values != 1 OR values != 2
Also you can use this as WHERE:
WHERE values > 2
SELECT Id, Values
FROM table2
WHERE Id Not in (select Id from table2 where Values IN (1,2))
this is your query

How to replace rows with duplicated values in Access?

I have 2 tables and I'd like to substitute rows from Table1 where Customer value is duplicated (for example, B) with a row from Table2 with the same Customer.
Table 1:
Customer cod
A 2
B 1
B N/A
C 5
Table 2:
Customer cod
B 123
So the result should be:
Customer cod
A 2
B 123
C 5
The code could be something like:
INSERT INTO Table1
SELECT *
FROM Table2, Table1
WHERE Table1.Customer = Table2.Customer;
First insert wanted data from table2
INSERT INTO Table1
SELECT *
FROM Table2 t21
WHERE (SELECT count(*)
FROM Table1 t12
WHERE t12.Customer=t21.Customer) > 1;
Then remove duuplicates from table1 which are not matching cod from table 2
DELETE
FROM Table1 t11
WHERE ((SELECT count(*)
FROM Table1 t12
WHERE t11.Customer = t12.Customer)>1
AND NOT cod IN (SELECT cod
FROM Table2 t21
WHERE t11.Customer=t21.Customer))
OR t11.cod IS NULL;