How to join two SQLite Tables where key is not exact the same int value? - sqlite

I have two tables, where the on joining key is not exact the same integer value.
How can I join with the best match (the difference should be minimal) on these keys?
Here is my Table Demo Dump.
CREATE TABLE t1(
"size" TEXT,
filename TEXT
);
-- ----------------------------
-- Records of matching
-- ----------------------------
INSERT INTO "main"."t1" VALUES (1162775, file1);
INSERT INTO "main"."t1" VALUES (1145387, file1);
INSERT INTO "main"."t1" VALUES (1388613, file1);
INSERT INTO "main"."t1" VALUES (1306413, file1);
INSERT INTO "main"."t1" VALUES (1792882, file1);
INSERT INTO "main"."t1" VALUES (1798382, file1);
INSERT INTO "main"."t1" VALUES (878147, file1);
INSERT INTO "main"."t1" VALUES (2614277, file1);
INSERT INTO "main"."t1" VALUES (838639, file1);
INSERT INTO "main"."t1" VALUES (3053906, file1);
INSERT INTO "main"."t1" VALUES (1019579, file1);
INSERT INTO "main"."t1" VALUES (3234508, file1);
INSERT INTO "main"."t1" VALUES (2442681, file1);
CREATE TABLE t2(
"info" Text,
readysize TEXT
);
-- ----------------------------
-- Records of matching
-- ----------------------------
INSERT INTO "main"."t2" VALUES (info1, 1162780);
INSERT INTO "main"."t2" VALUES (info1, 1145392);
INSERT INTO "main"."t2" VALUES (info1, 1388620);
INSERT INTO "main"."t2" VALUES (info1, 1306420);
INSERT INTO "main"."t2" VALUES (info1, 1792888);
INSERT INTO "main"."t2" VALUES (info1, 1798388);
INSERT INTO "main"."t2" VALUES (info1, 878152 );
INSERT INTO "main"."t2" VALUES (info1, 2614284);
INSERT INTO "main"."t2" VALUES (info1, 838644 );
INSERT INTO "main"."t2" VALUES (info1, 3053912);
INSERT INTO "main"."t2" VALUES (info1, 1019584);
INSERT INTO "main"."t2" VALUES (info1, 3234516);
INSERT INTO "main"."t2" VALUES (info1, 2442688);
These key relation should be obtained as best fit:
1162775 -> 1162780
1145387 -> 1145392
1388613 -> 1388620
1306413 -> 1306420
1792882 -> 1792888
1798382 -> 1798388
878147 -> 878152
2614277 -> 2614284
838639 -> 838644
3053906 -> 3053912
1019579 -> 1019584
3234508 -> 3234516
2442681 -> 2442688
I would like that the on part of select * from t1 join t2 on t1.size (match best fit) t2.readysize so that for the first line the on should match 1162775 to 1162780 and so on.
PS: Well I think the on key could like this be done:
select * from t1 join t2 on abs(t1.size - t2.readysize) < 10 and ((t1.size >= t2.readysize) or (t1.size <= t2.readysize))
would this make sense?
So I have defined a delta which is max 10 f.e. and the absolut position by the and limiting.

Use a CROSS JOIN of the tables and aggregation, utilizing SQLite's feature of bare columns:
SELECT *,
MIN(ABS(t1.size - t2.readysize)) AS diff
FROM t1 JOIN t2
GROUP BY t1.rowid;
You may change rowid with the primary key of t1.
See the demo.

Related

SQLite3 run a trigger insert multiple times besed on inserted vlaue

Want to run an insert n-times, the n is defined by inserted value on another table.
table 1:
create table Table1
(
id INTEGER default 1 not null
primary key
unique,
name TEXT not null
unique,
keys_number INTEGER default 1 not null
);
table 2:
create table table_2
(
id INTEGER default 1 not null
primary key
unique,
table_1_id INTEGER not null
references table_1,
);
Now when i insert into table_1 like:
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name', 5)
want to run a trigger
CREATE TRIGGER insert_keys_after_insert_table_1
AFTER INSERT ON table_1
WHEN (SELECT COUNT(*) FROM table_2 WHERE table_1_id=new.id) < new.keys_number
BEGIN
INSERT INTO keys (table_1_id) VALUES (new.id);
END;
But this runs only once.
Finally, I want to have on table_2 values after the trigger
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name_1', 5)
make the result like:
id;name;keys_number
1;dummy_name_1;5
and the result on table_2 after the trigger, should be
id;table_1_id
1;1
2;1
3;1
4;1
5;1
or if I insert another one on table_1
INSERT INT table_1 (name, keys_number) VALUES ('dummy_name_2', 2)
will make the result on table_1 like:
id;name;keys_number
1;dummy_name_1;5
2;dummy_name_2;2
and the trigger will give the result on table_2:
id;table_1_id
1;1
2;1
3;1
4;1
5;1
6;2
7;2
For this requirement you need a loop, which in SQL is implemented via a recursive CTE.
Unfortunately SQLite does not allow CTEs inside a trigger.
A workaround is to create a new table with only 1 column which will store the numbers 1 to the max expected value of keys_number in table_1:
CREATE TABLE table_numbers AS
WITH cte(keys_number) AS (
SELECT 1
UNION ALL
SELECT keys_number + 1 FROM cte WHERE keys_number < 100 -- change 100 to the max keys_number you expect
)
SELECT keys_number FROM cte
Now you can create your trigger:
CREATE TRIGGER insert_keys_after_insert_table_1 AFTER INSERT ON table_1
BEGIN
INSERT INTO table_2(table_1_id)
SELECT NEW.id
FROM table_numbers
WHERE keys_number <= NEW.keys_number - (SELECT COUNT(*) FROM table_2 WHERE table_1_id = NEW.id);
END;
See the demo.

Updating single specified values from another table in SQLite

I have two SQLite tables A and B defined as:
CREATE TABLE A (orig_cat INTEGER, type INTEGER,gv_ID INTEGER);
INSERT INTO A (orig_cat,type) VALUES (1,1);
INSERT INTO A (orig_cat,type) VALUES (2,2);
INSERT INTO A (orig_cat,type) VALUES (3,2);
INSERT INTO A (orig_cat,type) VALUES (4,2);
INSERT INTO A (orig_cat,type) VALUES (1,3);
INSERT INTO A (orig_cat,type) VALUES (2,3);
INSERT INTO A (orig_cat,type) VALUES (3,3);
UPDATE A SET gv_ID=rowid+99;
and
CREATE TABLE B (col_t INTEGER, orig_cat INTEGER, part INTEGER);
INSERT INTO B VALUES (1,1,1);
INSERT INTO B VALUES (3,1,2);
INSERT INTO B VALUES (2,2,1);
INSERT INTO B VALUES (1,2,2);
INSERT INTO B VALUES (3,3,1);
INSERT INTO B VALUES (4,3,2);
I'd like to update and set/replace the values in column col_t of table B where part=2 with selected values of column gv_ID of table A. The selected values I can get with a SELECT command:
SELECT gv_ID
FROM (SELECT * FROM B where part=2) AS B_sub
JOIN (SELECT * FROM A WHERE type=3) AS A_sub
ON B_sub.orig_cat=A_sub.orig_cat;
How can I use that so that the values of col_t in rows 2,3 and 5 (=1,2,3) get replaced with the values 104,105,106 (wich is returned by the selection)?
You can use correlated subquery:
UPDATE B
SET col_t = (SELECT gv_ID FROM A WHERE A.orig_cat = B.orig_cat AND A.type = 3)
WHERE B."part" = 2;
SqlFiddleDemo
I've assumed that pair A.orig_cat and A.type is UNIQUE.

sqlite3: how to select same row twice when there is a match?

Create SOF.SQL
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US');
INSERT INTO "android_metadata" VALUES ('en_US');
CREATE TABLE main.t_def (
_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
word TEXT(20) not null,
word_def TEXT(20) not null
);
insert into t_def (word, word_def) values ('ball','spherical object');
insert into t_def (word, word_def) values ('cat','feline');
insert into t_def (word, word_def) values ('dog','common housekept');
CREATE TABLE main.t_a (
_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
corr_answer TEXT(20) not null,
user_answer TEXT(20) not null,
is_correct INTEGER not null
);
insert into t_a (user_answer, corr_answer, is_correct) values ('ball','cat',0);
insert into t_a (user_answer, corr_answer, is_correct) values ('dog','dog',1);
.exit
Then run:
sqlite3 foo.db < SOF.SQL
I want a result set that is:
ball|spherical object|cat|feline|0
This is the closest I have gotten:
select t_def.word, t_def.word_def from t_def, t_a where t_a.is_correct=0 and t_a.corr_answer=t_def.word;
To get values from two rows, you need two instances of the table:
SELECT t_a.user_answer,
user_def.word_def AS user_word_def,
t_a.corr_answer,
corr_def.word_def AS corr_word_def,
t_a.is_correct
FROM t_a
JOIN t_def AS user_def ON t_a.user_answer = user_def.word
JOIN t_def AS corr_def ON t_a.corr_answer = corr_def.word
WHERE NOT t_a.is_correct

Delete data using merge statement in Oracle

How to only delete data using merge using oracle...
I am using the below code:
Merge
into
target_table
using
source_tablle
on (...)
when matched
then delete
But I am getting an error "missing Keyword" at last line
Your MERGE at the end is missing the UPDATE clause.
Lets look at a sample MERGE
CREATE TABLE employee (
employee_id NUMBER(5),
first_name VARCHAR2(20),
last_name VARCHAR2(20),
dept_no NUMBER(2),
salary NUMBER(10));
INSERT INTO employee VALUES (1, 'Dan', 'Morgan', 10, 100000);
INSERT INTO employee VALUES (2, 'Helen', 'Lofstrom', 20, 100000);
INSERT INTO employee VALUES (3, 'Akiko', 'Toyota', 20, 50000);
INSERT INTO employee VALUES (4, 'Jackie', 'Stough', 20, 40000);
INSERT INTO employee VALUES (5, 'Richard', 'Foote', 20, 70000);
INSERT INTO employee VALUES (6, 'Joe', 'Johnson', 20, 30000);
INSERT INTO employee VALUES (7, 'Clark', 'Urling', 20, 90000);
CREATE TABLE bonuses (
employee_id NUMBER, bonus NUMBER DEFAULT 100);
INSERT INTO bonuses (employee_id) VALUES (1);
INSERT INTO bonuses (employee_id) VALUES (2);
INSERT INTO bonuses (employee_id) VALUES (4);
INSERT INTO bonuses (employee_id) VALUES (6);
INSERT INTO bonuses (employee_id) VALUES (7);
COMMIT;
Now we have a sample data structure lets do some merging:
MERGE INTO bonuses b
USING (
SELECT employee_id, salary, dept_no
FROM employee
WHERE dept_no =20) e
ON (b.employee_id = e.employee_id)
WHEN MATCHED THEN
UPDATE SET b.bonus = e.salary * 0.1
DELETE WHERE (e.salary < 40000)
;
So this command the MERGE syntax using the merge_update_clause:
MERGE INTO (table/view)
USING (table/view)
ON (condition)
WHEN MATCHED THEN
UPDATE SET (column..expression)
DELETE WHERE (condition)
I guess what I'm hinting at is that you are missing your UPDATE SET clause as well as the DELETE conditions. I recommend following up on the MERGE syntax.
**Edit:**SQLFiddle is back so here you go.

how to join more than one sqlite tables

I have 7 Sqlite tables and i want to join all these into one table or say a new table .Every tables has same number of column names.I am getting error ambiguity with column name.How can join all these tables.
To avoid ambiguity, you should prefix the columns with the table names and use column aliases:
create table tab1(id number, value varchar2(20));
create table tab2(id number, value varchar2(20));
create table tab3(id number, value varchar2(20));
insert into tab1(id, value) values(1, 'a');
insert into tab2(id, value) values(1, 'b');
insert into tab3(id, value) values(1, 'c');
create table t4 as
select tab1.id id, tab1.value value1, tab2.value value2, tab3.value value3
from tab1, tab2, tab3
where tab1.id = tab2.id
and tab1.id = tab3.id;

Resources