update _ids values by sorted timestamp with sql - sql

i have a few tables look like below (sqlite)
table a:
a_id (unique)
timestamp
21
123
2
178
33
101
7
221
4
115
table b:
b_id (unique)
a_id
data (no need to sort)
14
4
bb
3
2
dd
22
21
ee
6
7
xx
17
2
tt
11
33
qq
now i want to update these tables' _id according to the timestamp in a as follows:
table a:
a_id
timestamp
1
101
2
115
3
123
4
178
5
221
table b:
b_id
a_id
data
1
1
qq
2
2
bb
3
3
ee
4
4
dd
5
2
tt
6
5
xx
how can i do this easily with sql, without re inserting the data etc?
thanks
i used to create a dummy column with new and sorted ids by timestamp, then update other tables accordingly but it was inefficient and i have forgotten how i did it
update:
to simplify, i want to create a new column sort_id in table a, which holds the value according to the sorted timestamp, so
before:
table a
a_id (unique)
timestamp
21
123
2
178
33
101
7
221
4
115
after:
table a
a_id (unique)
timestamp
sort_id
21
123
3
2
178
4
33
101
1
7
221
5
4
115
2
so how can i fill the sort_id column according to the timestamp?

you want to query your table b data and sort it based on time stamp .
order of rows in a database is not guaranteed at all and it changes anytime after each insert/update, so you need to join two tables and sort based on timestamp column :
select b.*
from table_b b
left join table_a a
on a.a_id = b.a_id
order by a.timestamp
depending on your sqlite version you also can use update from :
update tableb
set sort_id = rn
from (select a_id , row_number() over (order by timestamp) as rn from tableA) tableA
where tableA.a_id = tableB.a_.id

Aftrer you've altered the table to add the new column...
WITH
sorted AS
(
SELECT
a_id,
ROW_NUMBER() OVER (ORDER BY timestamp) AS new_sort_id
FROM
table_a
)
UPDATE
table_a
SET
sort_id = sorted.new_sort_id
FROM
sorted
WHERE
table_a.a_id = sorted.a_id

Related

How to fetch records up to particular data

Table tb data as below
id remarks status key
------------------------------------
1 dfe 1 340
2 ert 4 340
3 aaa 6 340
4 gh 7 340
5 bnh 2 341
6 xdc 6 341
7 qqq 1 341
8 rty 3 343
9 mnh 1 343
10 ppo 3 343
11 oit 6 343
I want to get list of id upto status 6 by grouping key.
select id
from tb
where status in (6) AND key in (select key_list from temporary_table)
group by key;
I didnt get required records.
For example: I need output as below for
key 340
id
---
1
2
3
For key 341
id
---
5
6
For key 343
id
---
8
9
10
11
Note: Orginal key column data not in order, it is in suffle. For easy understanding in given list this.
You can use a correlated subquery:
select tb.* -- or whatever columns you want
from tb
where tb.id <= (select min(tb2.id)
from tb tb2
where tb2.key = tb.key and tb2.status = 6
);
Alternatively, you can use a window function:
select tb.id
from (select tb.*,
min(case when status = 6 then id end) over (partition by key) as id_6
from tb
) tb
where id <= id_6;
Assuming that
You need a query to return the respective id's for all keys in a
single query;
If for a given key the status is never 6, then you must return all
the rows for that key
you can do this with match_recognize:
select key, id
from tb
match_recognize(
partition by key
order by id
all rows per match
pattern ( ^ a* b? )
define a as status != 6
);
If, instead, you must give the query a single input key as a variable, and return the result just for that key, you can modify the query like this:
select id
from (select id, status from tb where key = :input_key)
match_recognize(
order by id
all rows per match
pattern ( ^ a* b? )
define a as status != 6
);

How to update a column with incrementally sequenced values that change depending on other column value

I am trying to update a column in a table so that the Index column (which is currently arbitrary numbers) is renumbered sequentially starting at 1000 with increments of 10, and this sequence restarts every time the Group changes.
I have tried ROWNUMBER() with PARTITION and trying to define a SEQUENCE, but I can't seem to get the result I'm looking for.
Table 1
ID Group Index
1 A 1
2 A 2
3 B 3
4 B 4
5 B 5
6 C 6
7 D 7
What I want:
Table 1
ID Group Index
1 A 1000
2 A 1010
3 B 1000
4 B 1010
5 B 1020
6 C 1000
7 D 1000
You can use row_number() with some arithmetic:
select t.*,
990 + 10 * row_number() over (partition by group order by id) as index
from t;
Note that group and index are SQL reserved words, so they are really bad column names.

SQL copy from one table to another with changing ID value

I have two tables:
A
ID VALUE
----------
1 7
2 5
3 44
4 982
5 1
6 0
7 671
B
ID VALUE
---------------
1 6
2 6
3 77
4 22
How do I copy data from #B to #A to get a different ID (one bigger than the MAX in #A)? For example I need to get
ID VALUE
1 7
2 5
3 44
4 982
5 1
6 0
7 671
8 6
9 6
10 77
11 22
Either make it an IDENTITY column which auto-increments, or this:
INSERT INTO A
SELECT b.ID + (SELECT MAX(ID) FROM A) AS ID, b.Value
FROM B
DEMO
The select is slightly different if the ID in table B has gaps. Then those gaps are transferred.
If the ID column in TableA is not already set to auto-increment, do the following command:
ALTER TABLE TableA MODIFY COLUMN ID INT auto_increment
Now you can just insert all the records from TableB into TableA:
INSERT INTO TableA (VALUE)
SELECT VALUE
FROM TableB
It is not a great idea to rely on the business logic in your query to maintain the order of the ID column. Instead, let SQL take care of it for you; it was designed for this purpose.

Keeping track of auto increment columns in a cursor

I wrote a cursor where I needed to copy some rows and insert it into a table with only 1 column different. Say for example I have a table A like this
Id | CID | Country
1 X A
2 X B
3 X C
'Id' in this table is auto increment and primary key and Country is the countries visited by that CID. So when I was asked to update the table where every country visited by CID 'X' has also been visited by CID 'Y'. I wrote a cursor and did an insert into with CID 'Y' and the Country. After I executed my cursor, table A became this:
Id | CID | Country
1 X A
2 X B
3 X C
4 Y A
5 Y B
6 Y C
Now there is another table B that is as follows, where AId is the foreign key referencing Id in A.
AId | AgeOfKids
1 20
1 23
1 28
2 21
2 24
2 29
3 22
3 25
I want to be able to add rows to this table such that it becomes:
AId | AgeOfKids
1 20
1 23
1 28
2 21
2 24
2 29
3 22
3 25
4 20
4 23
4 28
5 21
5 24
5 29
6 22
6 25
To explain in words, the AIds that have the same countries in table A must have the same BeIds in table B. Is it possible to accomplish this? Is so, how can I accomplish this?
Use the OUTPUT clause:
declare #t table (Id int not null,Country char(1) not null)
insert into TableA (CID,Country)
output inserted.id,inserted.Country into #t
select 'Y',Country from TableA where CID = 'X'
And then (should be part of the same batch as the above):
insert into TableB (AId,AgeOfKids)
select t.ID,b.AgeOfKids
from #t t
inner join
TableA a
on
t.Country = a.Country and
a.CID = 'X'
inner join
TableB b
on
a.ID = b.AId
To populate table B.

How to find distance between two columns in different tables in geom datatype

Update the value in the column "distance" of table 1 by finding the distance between center_geom from table2 and home_location from table 3.
Table 1
obu_id end_location trip_id end_loc_adj distance
1 51 1234
2 57 1357 44
2 63 1351
3 21 1212 20
3 23 4313
Table 2
id obu_id center_geom
int int geom
51 2 "0101000020ED0800006DFFCAA2A2553341B20E4717774E0C41"
52 3 "0101000020ED080000AE47E17A35F73341FE65F764723C0841"
57 3 "0101000020ED0800006DFFCAA2A2553341B20E4717774E0C41"
21 4 "0101000020ED080000B81E852BC555334186048C9EB1C21141"
Now, see table 1: If we have any value in end_loc_adj then the column : end_loc_adj has to be used rather end_loc Hint: use if-else.
Column name "end_loc" in table 1 has same values as column "id" in table 2.
Table 3
hhid obu_id home_location
(character Int geometry
varying)
11 1 "0101000020ED08000082E2C7A0B2413341BC5818A21F000941"
15 2 "0101000020ED080000B81E852BC555334186048C9EB1C21141"
17 3 "0101000020ED0800006DFFCAA2A2553341B20E4717774E0C41"
17 4 "0101000020ED080000B81E852BC555334186048C9EB1C21141"
22 7 "0101000020ED080000AE47E17A35F73341FE65F764723C0841"
I have tried the following:
select ST_Distance_Sphere ( ST_AsText(cast(v.house_location AS text)) , ST_AsText(cast(l.center AS text)))
from public.locations l, clean.vehicles v
where l.obu_id=v.obu_id
and l.obu_id=3
but this works manually for single obu_id
I want to complete it in one go using a function.
Please give me some idea about how to do this.
Thanks.
house_loc:=(select house_location from table1 where obu_id=b.obu_id);
house_loc_geom := ST_Transform(house_loc,4269);
IF b.end_location_adj IS null THEN
end_loc:= (select center from table2 where id=b.end_location and obu_id= b.obu_id);
else
end_loc:= (select center from tabl2 where id = b.end_location_adj and obu_id = b.obu_id);
end if;
center_geom:=ST_Transform(end_loc,4269);
UPDATE table 1 set dist_from_home_in_meter=distance
where obu_id=b.obu_id and trip_id=b.trip_id and end_location=b.end_location;
this is close to answer, need some modifications.