sqlite delete all results where column a and column b is not in first n items - sql

Lets say I have the following table
a b c
-----------
1 1 5
1 2 3
4 1 2
1 2 4
4 2 10
And I want to delete all rows where none of the first n rows has the same value in a and b as that row.
So for example the resulting tables for various n's would be
n = 1
a b c
-----------
1 1 5
// No row other than the first has a 1 in a, and a 1 in b
n = 2
a b c
-----------
1 1 5
1 2 3
1 2 4
// The fourth row has the same values in a and b as the second, so it is not deleted. The first 2 rows of course match themselves so are not deleted
n = 3
a b c
-----------
1 1 5
1 2 3
4 1 2
1 2 4
// The fourth row has the same values in a and b as the second, so it is not deleted. The first 3 rows of course match themselves so are not deleted
n = 4
a b c
-----------
1 1 5
1 2 3
4 1 2
1 2 4
// The first 4 rows of course match themselves so are not deleted. The fifth row does not have the same value in both a and b as any of the first 4 rows, so is deleted.
I've been trying to work out how to do this using a not in or a not exists, but since I'm interested in two columns matching not just 1 or the whole record, I'm struggling.

Since you are not defining a specific order, the result is not completely defined, but depends on arbitrary choices of implementation regarding which rows are computed first in the limit clause. A different SQLite version for example may give you a different result. With that being said, I believe that you want the following query:
select t1.* from table1 t1,
(select distinct t2.a, t2.b from table1 t2 limit N) tabledist
where t1.a=tabledist.a and t1.b=tabledist.b;
where you should replace N with the desired number of rows
EDIT: So, to delete directly from the existing table you need something like:
with toremove(a, b, c) as
(select * from table1 tt
EXCEPT select t1.* from table1 t1,
(select distinct t2.a, t2.b from table1 t2 limit N) tabledist
where t1.a=tabledist.a and t1.b=tabledist.b)
delete from table1 where exists
(select * from toremove
where table1.a=toremove.a and table1.b=toremove.b and table1.c=toremove.c);

Related

LEFT JOIN with tables having boolean data producing unexpected result set

A Table_1 with only column BOOLVALUE(int) having records as
1
1
0
0
0
and another Table_2 with only column BOOLVALUE(int) having records as
1
1
1
0
0
.. I am trying to run a query
select t1.BOOLVALUE from Table_1 t1
left join Table_2 t2 on t1.BOOLVALUE=t2.BOOLVALUE
and to my surprise output is not what I expected.There are 12 rows with 6 1's and 6 0's. But doesn't this invalidates how joins work ?
12 rows is completely expected as you have 2 rows related to 3 rows, resulting in 6 rows, and 3 rows related to 2 rows resulting in 6 rows; add these together and you get 12.
When you JOIN all related rows are JOINed based on the ON clause. Your ON clause is t1.BOOLVALUE=t2.BOOLVALUE. This means all the 1s inTable_1 relate to all the 1s in Table_2; so that's 2 rows related to 3 rows (2 * 3). Then all the 0s inTable_1 relate to all the 0s in Table_2; so that's 3 rows related to 2 rows (3 * 2). Hence (2 * 3) + (3 * 2) = 6 + 6 = 12.
If we add an ID column to the table, this might become a little clearer.
Let's say you have 2 tables like this:
ID1
I1
1
1
2
1
3
0
4
0
5
0
ID2
I2
1
1
2
1
3
1
4
0
5
0
Then lets say you have the following query:
SELECT T1.ID1,
T2.ID2,
T1.I1,
T2.I2
FROM dbo.Table1 T1
JOIN dbo.Table2 T2 ON T1.I1 = T2.I2
ORDER BY T1.ID1
T2.ID2;
This would result in the following data set:
ID1
ID2
I1
I2
1
1
1
1
1
2
1
1
1
3
1
1
2
1
1
1
2
2
1
1
2
3
1
1
3
4
0
0
3
5
0
0
4
4
0
0
4
5
0
0
5
4
0
0
5
5
0
0
Here you can see you have a many to many join, and where the "extra" rows are coming from.
If you LEFT JOINed on the ID and I columns, starting at Table1, you would get 5 rows, with 1 row having NULL values for ID2 and I2 (in this case because although the ID matched, I did not):
SELECT T1.ID1,
T2.ID2,
T1.I1,
T2.I2
FROM dbo.Table1 T1
LEFT JOIN dbo.Table2 T2 ON T1.ID1 = T2.ID1
AND T1.I1 = T2.I2
ORDER BY T1.ID1
T2.ID2;
ID1
ID2
I1
I2
1
1
1
1
2
2
1
1
3
NULL
0
NULL
4
4
0
0
5
5
0
0
When you join on a column of which has repeating values the number of rows returned is the product of the number of matching values in the 2 tables.
In this case there are 2 1's in table 1 and 3 in table 2 so SQL returns the 6 possible combinations (2 x 3). As there are 3 x 2 zero combinations you get 12 rows in total.
If you did a cross join you would get 25 rows back (5 x 5).

If the two tables are inner joined, what will be the output?

Table A: 1 1 1 2 2 3 3 3 4 4
Table B: 1 1 2 2 3 3 5 5 5
What will be the output if the two tables are inner joined?
My answer was 1 1 2 2 3 3 but the interviewer said it wrong :/
According to my knowledge, inner join means the common factors of two tables. What should be my approach to this question?
Answer will be :
1
1
1
1
1
1
2
2
2
2
3
3
3
3
3
3
db<>fiddle demo
Let me explain for 1:
There are three rows containing 1 in TableA and two rows with 1 in TableB, so the final output will have 3*2 = six 1. Similarly for the other values.
It depends entirely on what the query is. If you do:
select *
from a join
b
on 1=0;
You will get no rows.
If you do:
select *
from t1 join
t2
on 1=1;
You will generate a Cartesian product.
If you do:
select *
from a join
b
on a.col = 4 and b.col = 2;
You will get 4 rows with 4 2 repeated four times.
If you do:
select *
from a join
b
on b.col^2 = a.col^3 + 1;
You will get four rows each with 2 and 3.
And so on.
Your question doesn't have enough information.

PLSQL UPDATE BASED ON ROWS FROM OTHER TABLE

I have following tables in APEX A and B.
A has columns:
ID_A;
VALUE;
B has columns:
ID_C_FK;
ID_A_FK
I want to update the VALUE column in table A in rows where ID_A equals ID_A_FK in selected rows from table B where ID_C_FK equal x
For example: A has rows (
ID_A value
------------
1 1
2 1
3 0
4 0
5 0
Table B has rows
ID_C_FK ID_A_FK
------------------
8 4
9 4
9 5
I want to update VALUE in table A only for those rows that have ID_A in rows selected from B and condition to select rows from B is that ID_C_FK equals x = 9; and as a result, table A should end up having rows:
ID_A value
------------
1 1
2 1
3 0
4 1
5 1
How to write such update in PL/SQL?
Thank you for considering my request.
I think this is what you want:
update a
set value = 1
where exists (select 1
from b
where b.id_a_fk = a.id_a and b.id_c_fk = 9
);

Combine two result sets and still keep one of the columns unique

I have two intermediate result sets in a create view statement. The result sets are derived from two different join paths and I need to union them. But it doesn't stop here. Since the ID column needs to be unique, I will then need the rows in result set 2 that contains the same IDs as the first result set to overwrite the same rows in the first result set.
Let me illustrate this here:
Result set 1
ID Value
------------
1 a
3 a
5 a
6 a
7 a
8 a
Result Set 2
ID Value
------------
2 b
4 b
5 b
7 b
9 b
10 b
End result set
ID value
------------
1 a
2 b
3 a
4 b
5 b
6 a
7 b
8 a
9 b
10 b
I am not sure how to approach this. Union/except/intersect will create duplicate ids, so that's no good.
SELECT COALESCE(set2.ID, set1.ID) AS ID,
CASE WHEN set2.ID IS NULL THEN set1.Value ELSE set2.Value END AS Value
FROM set1
FULL JOIN set2
ON set1.ID = set2.ID
Try deleting elements from result set 1 where id exists in result set 2 before union all.

why 9 rows are fetch from this query?

Given 2 tables T1 and T2.
T1 T2
A 1
B 2
C 3
You make a query SELECT * FROM T1, T2.
What is the no: of rows that are fetched from this query?
Answer is 9
This query results in cartesian product because no other conditions are provided. Every row from first table is matched with every row from second table.
The result is
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3
Because each record from the first table is returned along with each record of the second table and the result is not filtered.
The exact output will be:
T1 T2
A 1
A 2
A 3
B 1
B 2
B 3
C 1
C 2
C 3
(order may vary)
It is a cartesian product: select all rows from one table (3) and all rows from another table (3) and combine them, so 3*3=9.
That's what you asked it to do. You got all the rows from T1 and all the rows from T2. They don't just get added together -- that won't work if the columns are different, for example, though you can do this with UNION -- they get merged in what's known as a "cartesian product". You essentially get all combinations of rows from both tables. And 3*3 = 9.